This commit is contained in:
2025-04-24 18:31:27 +08:00
commit 9340f5253e
2796 changed files with 1387124 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
namespace SwashbuckleEx.WebApiTest
{
/// <summary>
/// 简单Cors跨域处理器
/// </summary>
public class SimpleCorsHandler : DelegatingHandler
{
private const string Origin = "Origin";
private const string AccessControlRequestMethod = "Access-Control-Request-Method";
private const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
private const string AccessControlAllowOrign = "Access-Control-Allow-Origin";
private const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
private const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
private const string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";
private const string AccessControlMaxAge = "Access-Control-Max-Age";
// <add name = "Access-Control-Allow-Headers" value="Content-Type" />
// <add name = "Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
bool isCrosRequest = request.Headers.Contains(Origin);
bool isPrefilightRequest = request.Method == HttpMethod.Options;
if (isCrosRequest)
{
Task<HttpResponseMessage> taskResult = null;
if (isPrefilightRequest)
{
taskResult = Task.Factory.StartNew<HttpResponseMessage>(() =>
{
HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
response.Headers.Add(AccessControlAllowOrign,
request.Headers.GetValues(Origin).FirstOrDefault());
string method = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
//if (method != null)
//{
// response.Headers.Add(AccessControlAllowMethods, method);
//}
string headers = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));
if (!string.IsNullOrWhiteSpace(headers))
{
response.Headers.Add(AccessControlAllowHeaders, headers);
}
response.Headers.Add(AccessControlAllowCredentials, "true");
response.Headers.Add(AccessControlMaxAge, "1728000");
return response;
}, cancellationToken);
}
else
{
taskResult = base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(t =>
{
var response = t.Result;
response.Headers.Add(AccessControlAllowOrign,
request.Headers.GetValues(Origin).FirstOrDefault());
response.Headers.Add(AccessControlAllowCredentials, "true");
return response;
});
}
return taskResult;
}
return base.SendAsync(request, cancellationToken);
}
//private const string Origin = "Origin";
//private const string AccessControlRequestMethod = "Access-Control-Request-Method";
//private const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
//private const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
//private const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
//private const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
//// 重写基类的发送消息方法
//protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
//{
// bool isCrosRequest = request.Headers.Contains(Origin);
// bool isPrefilightRequest = request.Method == HttpMethod.Options;
// if (isCrosRequest)
// {
// if (isPrefilightRequest)
// {
// return Task.Factory.StartNew(() =>
// {
// var response = new HttpResponseMessage(HttpStatusCode.OK);
// response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
// var currentAccessControlRequestMethod =
// request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
// if (currentAccessControlRequestMethod != null)
// {
// response.Headers.Add(AccessControlAllowMethods, currentAccessControlRequestMethod);
// }
// var requestedHeaders = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));
// if (!requestedHeaders.IsNullOrEmpty())
// {
// response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
// }
// return response;
// }, cancellationToken);
// }
// return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(t =>
// {
// var response = t.Result;
// response.Headers.Add(AccessControlAllowOrigin,
// request.Headers.GetValues(Origin).FirstOrDefault());
// return response;
// });
// }
// return base.SendAsync(request, cancellationToken);
//}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Http.Description;
using Swashbuckle.Application;
using SwashbuckleEx.WebApiTest;
using SwashbuckleEx.WebApiTest.Extensions;
using SwashbuckleEx.WebApiTest.Selectors;
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
namespace SwashbuckleEx.WebApiTest
{
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
// 配置简单API文档信息-用于单个文档
//c.SingleApiVersion("v1", "Test.WebApi").Contact(x =>
//{
// x.Email("jianxuanhuo1@126.com");
// x.Name("jian玄冰");
// x.Url("https://www.cnblogs.com/jianxuanbing");
//}).TermsOfService("jian玄冰1").License(x =>
//{
// x.Name("MIT");
// x.Url("https://www.cnblogs.com/jianxuanbing");
//}).Description("自定义文案内容,可以随便输入内容");
c.MultipleApiVersions(ResolveAreasSupportByRouteConstraint, (vc) =>
{
vc.Version("Admin", "中文后台 API").Description("这个用于测试一下备注信息").TermsOfService("www.baidu.com").License(
x =>
{
x.Name("jian玄冰");
x.Url("www.baidu.2333");
})
.Contact(x =>
{
x.Name("2017").Email("jianxuanhuo1@126.com").Url("www.baidu.xxxx");
});
vc.Version("v1", "Common API", true);
vc.Version("Client", "Client API");
});
c.ApiKey("Authorization").Description("OAuth2 Auth").In("header").Name("Authorization");
//c.OAuth2("jwt").AuthorizationUrl("http://localhost:9460/oauth/token")
// .TokenUrl("http://localhost:9460/oauth/token").Scopes(
// x =>
// {
// x.Add("scope", "admin");
// });
c.DocumentFilter<SwaggerAreasSupportDocumentFilter>();
c.OperationFilter<AddUploadOperationFilter>();
c.IncludeXmlComments(string.Format("{0}/bin/SwashbuckleEx.WebApiTest.XML", AppDomain.CurrentDomain.BaseDirectory));
c.ShowDeveloperInfo();
})
.EnableSwaggerUi(c =>
{
c.EnableApiKeySupport("Authorization","header");
});
}
private static bool ResolveAreasSupportByRouteConstraint(ApiDescription apiDescription, string targetApiVersion)
{
if (targetApiVersion == "v1")
{
return apiDescription.Route.RouteTemplate.StartsWith("api/{controller}");
}
var routeTemplateStart = "api/" + targetApiVersion;
return apiDescription.Route.RouteTemplate.StartsWith(routeTemplateStart);
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Dispatcher;
using SwashbuckleEx.WebApiTest.Selectors;
namespace SwashbuckleEx.WebApiTest
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API 配置和服务
config.Services.Replace(typeof(IHttpControllerSelector),new NamespaceHttpControllerSelector(config));
// Web API 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "AdminApi",
routeTemplate: "api/Admin/{controller}/{action}/{id}",
defaults: new { action = RouteParameter.Optional, id = RouteParameter.Optional, namespaces = new string[] { "SwashbuckleEx.WebApiTest.Areas.Admin.Controllers" } });
config.Routes.MapHttpRoute(
name: "ClientApi",
routeTemplate: "api/Client/{controller}/{action}/{id}",
defaults: new { action = RouteParameter.Optional, id = RouteParameter.Optional, namespaces = new string[] { "SwashbuckleEx.WebApiTest.Areas.Client.Controllers" } });
config.Routes.MapHttpRoute(
name: "CommonApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = RouteParameter.Optional, id = RouteParameter.Optional, namespaces = new string[] { "SwashbuckleEx.WebApiTest.Controllers" } }
);
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Swashbuckle.Swagger.Annotations;
using SwashbuckleEx.WebApiTest.Extensions;
using SwashbuckleEx.WebApiTest.Models;
namespace SwashbuckleEx.WebApiTest.Areas.Admin.Controllers
{
/// <summary>
/// 后台测试 相关API
/// </summary>
public class TestAController:ApiController
{
/// <summary>
///
/// </summary>
public TestAController()
{
}
/// <summary>
/// 获取后台Guid
/// </summary>
/// <remarks>
/// 测试一些内容,不想将无用的东西放在接口名称当中<br/>
/// 换行输出一下内容
/// </remarks>
/// <returns></returns>
[HttpGet]
public Guid GetGuid()
{
return Guid.NewGuid();
}
/// <summary>
/// 上传文件
/// </summary>
[HttpPost]
[Upload]
public void UploadFile()
{
}
/// <summary>
/// 查看API开发状态
/// </summary>
[HttpGet]
[ApiAuthor(Name = "jian玄冰", Status = DevStatus.Wait, Time = "2018-04-28")]
public void ApiStatus()
{
}
/// <summary>
/// 获取用户信息
/// </summary>
/// <returns></returns>
[HttpGet]
[SwaggerResponse(HttpStatusCode.OK,"自定义内容",Type = typeof(UserInfo))]
public HttpResponseMessage GetUserInfo()
{
return Request.CreateResponse(HttpStatusCode.OK, new UserInfo(), "application/json");
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
namespace SwashbuckleEx.WebApiTest.Areas.Client.Controllers
{
/// <summary>
/// 客户端测试 相关API
/// </summary>
public class TestAController:ApiController
{
/// <summary>
/// 获取客户端Guid
/// </summary>
/// <returns></returns>
[HttpGet]
[AllowAnonymous]
public Guid GetGuid()
{
return Guid.NewGuid();
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
namespace SwashbuckleEx.WebApiTest.Areas
{
/// <summary>
/// 扩展
/// </summary>
public static partial class Extensions
{
public static Route MapHttpRoute(this AreaRegistrationContext context, string name, string routeTemplate)
{
return context.MapHttpRoute(name, routeTemplate, null, null);
}
public static Route MapHttpRoute(this AreaRegistrationContext context, string name, string routeTemplate, object defaults)
{
return context.MapHttpRoute(name, routeTemplate, defaults, null);
}
public static Route MapHttpRoute(this AreaRegistrationContext context, string name, string routeTemplate, object defaults, object constraints)
{
var route = context.Routes.MapHttpRoute(name, routeTemplate, defaults, constraints);
if (route.DataTokens == null)
{
route.DataTokens = new RouteValueDictionary();
}
route.DataTokens.Add("area", context.AreaName);
return route;
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
namespace SwashbuckleEx.WebApiTest.Controllers
{
/// <summary>
/// 测试控制器
/// </summary>
public class TestAController:ApiController
{
/// <summary>
/// 获取通用ID
/// </summary>
/// <returns></returns>
[HttpGet]
public Guid GetId()
{
return Guid.NewGuid();
}
/// <summary>
/// 获取结果
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet]
public string GetResult(string id)
{
return id;
}
}
}

View File

@@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.Http.Description;
using Swashbuckle.Swagger;
namespace SwashbuckleEx.WebApiTest.Extensions
{
/// <summary>
/// 添加 上传操作过滤
/// </summary>
public class AddUploadOperationFilter : IOperationFilter
{
/// <summary>
/// 重写Apply方法加入Upload操作过滤
/// </summary>
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var upload = apiDescription.ActionDescriptor.GetCustomAttributes<UploadAttribute>().FirstOrDefault();
if (upload == null)
{
return;
}
operation.consumes.Add("application/form-data");
if (operation.parameters==null)
{
operation.parameters = new List<Parameter>();
}
operation.parameters.Add(new Parameter()
{
name = upload.Name,
@in = "formData",
required = upload.Require,
type = "file",
description = upload.Description
});
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
namespace SwashbuckleEx.WebApiTest.Extensions
{
/// <summary>
/// 上传属性,用于标识接口是否包含上传信息参数
/// </summary>
public class UploadAttribute : Attribute
{
/// <summary>
/// 参数名
/// </summary>
public string Name { get; set; } = "file";
/// <summary>
/// 是否必须包含文件
/// </summary>
public bool Require { get; set; } = true;
/// <summary>
/// 备注
/// </summary>
public string Description { get; set; } = "";
}
}

View File

@@ -0,0 +1 @@
<%@ Application Codebehind="Global.asax.cs" Inherits="SwashbuckleEx.WebApiTest.WebApiApplication" Language="C#" %>

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Http.Description;
using System.Web.Http.Dispatcher;
using System.Web.Mvc;
using System.Web.Routing;
using Swashbuckle.Application;
using SwashbuckleEx.WebApiTest.Selectors;
namespace SwashbuckleEx.WebApiTest
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
// WebApi支持Area
//GlobalConfiguration.Configuration.Services.Replace(typeof(IApiExplorer),
// new AreaApiExplorer(GlobalConfiguration.Configuration.Services.GetApiExplorer(),
// GlobalConfiguration.Configuration));
//GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector),
// new AreaHttpControllerSelector(GlobalConfiguration.Configuration));
GlobalConfiguration.Configuration.MessageHandlers.Add(new SimpleCorsHandler());
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SwashbuckleEx.WebApiTest.Models
{
/// <summary>
/// 用户信息
/// </summary>
public class UserInfo
{
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 手机号码
/// </summary>
public string Phone { get; set; }
/// <summary>
/// 头像
/// </summary>
public string Avactor { get; set; }
/// <summary>
/// 账号
/// </summary>
public string Account { get; set; }
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过下列特性集
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("SwashbuckleEx.WebApiTest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SwashbuckleEx.WebApiTest")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
// 对 COM 组件不可见。如果需要
// 从 COM 访问此程序集中的某个类型,请针对该类型将 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于 typelib 的 ID
[assembly: Guid("42bff3de-68b0-4dd0-96e1-2bf29975f522")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 内部版本号
// 修订版本
//
// 可以指定所有值,也可以使用“修订号”和“内部版本号”的默认值,
// 方法是按如下所示使用 "*":
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,127 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Web.Http.Routing;
namespace SwashbuckleEx.WebApiTest.Selectors
{
/// <summary>
/// WebApi区域控制器选择器
/// </summary>
public class AreaHttpControllerSelector : DefaultHttpControllerSelector
{
/// <summary>
/// 区域路由变量名
/// </summary>
private const string AreaRouteVariableName = "area";
/// <summary>
/// Http配置
/// </summary>
private readonly HttpConfiguration _configuration;
/// <summary>
/// Api控制器类型字典
/// </summary>
private readonly Lazy<ConcurrentDictionary<string, Type>> _apiControllerTypes;
/// <summary>
/// 初始化一个<see cref="AreaHttpControllerSelector"/>类型的实例
/// </summary>
/// <param name="configuration">Http配置</param>
public AreaHttpControllerSelector(HttpConfiguration configuration) : base(configuration)
{
_configuration = configuration;
_apiControllerTypes = new Lazy<ConcurrentDictionary<string, Type>>(GetControllerTypes);
}
/// <summary>
/// 获取控制器类型字典
/// </summary>
/// <returns></returns>
private static ConcurrentDictionary<string, Type> GetControllerTypes()
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
Dictionary<string, Type> types = assemblies
.SelectMany(a => a
.GetTypes().Where(t =>
!t.IsAbstract &&
t.Name.EndsWith(ControllerSuffix, StringComparison.OrdinalIgnoreCase) &&
typeof(IHttpController).IsAssignableFrom(t)))
.ToDictionary(t => t.FullName, t => t);
return new ConcurrentDictionary<string, Type>(types);
}
/// <summary>
/// 由Http请求获取控制台描述信息
/// </summary>
/// <param name="request">Http请求消息</param>
/// <returns></returns>
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
return GetApiController(request);
}
/// <summary>
/// 获取Api控制器
/// </summary>
/// <param name="request">Http请求消息</param>
/// <returns></returns>
private HttpControllerDescriptor GetApiController(HttpRequestMessage request)
{
string areaName = GetAreaName(request);
string controllerName = GetControllerName(request);
if (controllerName == null)
{
throw new InvalidOperationException("获取的Api控制器名称为空");
}
Type type = GetControllerType(areaName, controllerName);
return new HttpControllerDescriptor(_configuration, controllerName, type);
}
/// <summary>
/// 获取区域名
/// </summary>
/// <param name="request">Http请求消息</param>
/// <returns></returns>
private static string GetAreaName(HttpRequestMessage request)
{
IHttpRouteData data = request.GetRouteData();
object areaName;
if (data.Route == null || data.Route.DataTokens == null)
{
if (data.Values.TryGetValue(AreaRouteVariableName, out areaName))
{
return areaName.ToString();
}
return null;
}
return data.Route.DataTokens.TryGetValue(AreaRouteVariableName, out areaName) ? areaName.ToString() : null;
}
/// <summary>
/// 获取控制器类型
/// </summary>
/// <param name="areaName">区域名</param>
/// <param name="controllerName">控制器名</param>
/// <returns></returns>
private Type GetControllerType(string areaName, string controllerName)
{
IEnumerable<KeyValuePair<string, Type>> query = _apiControllerTypes.Value.AsEnumerable();
query = string.IsNullOrWhiteSpace(areaName) ? query.WithoutAreaName() : query.ByAreaName(areaName);
Type type = query.ByControllerName(controllerName).Select(m => m.Value).SingleOrDefault();
if (type == null)
{
throw new Exception(string.Format("未找到名称为“{0}”的Api控制器",controllerName));
}
return type;
}
}
}

View File

@@ -0,0 +1,172 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Web.Http.Routing;
namespace SwashbuckleEx.WebApiTest.Selectors
{
public class ClassifiedHttpControllerSelector:DefaultHttpControllerSelector
{
private const string AreaRouteVariableName = "area";
private const string CategoryRouteVariableName = "category";
private const string TheFixControllerFolderName = "Controllers";
private readonly HttpConfiguration _configuration;
private readonly Lazy<ILookup<string, Type>> _apiControllerTypes;
private ILookup<string, Type> ApiControllerTypes;
public ClassifiedHttpControllerSelector(HttpConfiguration configuration) : base(configuration)
{
_configuration = configuration;
_apiControllerTypes=new Lazy<ILookup<string, Type>>(GetApiControllerTypes);
}
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
//return GetApiController(request);
HttpControllerDescriptor des = null;
string controllerName = this.GetControllerName(request);
if (!string.IsNullOrWhiteSpace(controllerName))
{
var groups = this.ApiControllerTypes[controllerName.ToLower()];
if (groups != null && groups.Any())
{
string endString;
var routeDic = request.GetRouteData().Values;//存在controllerName的必定取到IHttpRouteData
if (routeDic.Count > 1)
{
StringBuilder sb=new StringBuilder();
foreach (var key in routeDic.Keys)
{
sb.Append(".");
sb.Append(routeDic[key]);
if (key.Equals(DefaultHttpControllerSelector.ControllerSuffix,
StringComparison.CurrentCultureIgnoreCase))
{
//如果是Control则代表命名空间结束
break;
}
}
sb.Append(DefaultHttpControllerSelector.ControllerSuffix);
endString = sb.ToString();
}
else
{
endString = string.Format(".{0}{1}", controllerName,
DefaultHttpControllerSelector.ControllerSuffix);
}
// 取NameSpace节点数最少的类型
var type =
groups.Where(t => t.FullName.EndsWith(endString, StringComparison.CurrentCultureIgnoreCase))
.OrderBy(t => t.FullName.Count(s => s == '.'))
.FirstOrDefault();//默认返回命名空间节点数最少的第一
if (type != null)
{
des=new HttpControllerDescriptor(this._configuration,controllerName,type);
}
}
}
if (des == null)
{
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
string.Format("No route providing a controller name was found to match request URI '{0}'",
request.RequestUri)));
}
return des;
}
private static string GetRouteValueByName(HttpRequestMessage request, string routeName)
{
IHttpRouteData data = request.GetRouteData();
if (data.Values.ContainsKey(routeName))
{
return data.Values[routeName] as string;
}
return null;
}
//private static ConcurrentDictionary<string, Type> GetAllControllerTypes()
//{
// Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
// Dictionary<string, Type> types =
// assemblies.SelectMany(
// x =>
// x.GetTypes()
// .Where(
// t =>
// !t.IsAbstract &&
// t.Name.EndsWith(ControllerSuffix, StringComparison.OrdinalIgnoreCase) &&
// typeof(IHttpController).IsAssignableFrom(t))).ToDictionary(t => t.FullName, t => t);
// return new ConcurrentDictionary<string, Type>(types);
//}
private ILookup<string, Type> GetApiControllerTypes()
{
IAssembliesResolver assembliesResolver = this._configuration.Services.GetAssembliesResolver();
return
this._configuration.Services.GetHttpControllerTypeResolver()
.GetControllerTypes(assembliesResolver)
.ToLookup(
t =>
t.Name.ToLower()
.Substring(0, t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length),
t => t);
}
//private HttpControllerDescriptor GetApiController(HttpRequestMessage request)
//{
// string areaName = GetRouteValueByName(request, AreaRouteVariableName);
// string categoryName = GetRouteValueByName(request, CategoryRouteVariableName);
// string controllerName = GetControllerName(request);
// Type type;
// try
// {
// type = GetControllerType(areaName, categoryName, controllerName);
// }
// catch (Exception)
// {
// return null;
// }
// return new HttpControllerDescriptor(_configuration,controllerName,type);
//}
//private Type GetControllerType(string areaName, string categoryName, string controllerName)
//{
// IEnumerable<KeyValuePair<string, Type>> query = _apiControllerTypes.Value.AsEnumerable();
// string controllerSearchingName;
// if (string.IsNullOrEmpty(areaName))
// {
// controllerSearchingName = TheFixControllerFolderName + "." + controllerName;
// }
// else
// {
// if (string.IsNullOrEmpty(categoryName))
// {
// controllerSearchingName = TheFixControllerFolderName + "." + areaName + "." + controllerName;
// }
// else
// {
// controllerSearchingName = TheFixControllerFolderName + "." + areaName + "." + categoryName + "." +
// controllerName;
// }
// }
// return
// query.Where(x => x.Key.IndexOf(controllerSearchingName, StringComparison.OrdinalIgnoreCase) != -1)
// .Select(x => x.Value)
// .SingleOrDefault();
//}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Http.Dispatcher;
namespace SwashbuckleEx.WebApiTest.Selectors
{
/// <summary>
/// 控制器类型规范 扩展
/// </summary>
internal static class ControllerTypeSpecifications
{
/// <summary>
/// 根据区域名获取键值对
/// </summary>
/// <param name="query">键值对列表</param>
/// <param name="areaName">区域名</param>
/// <returns></returns>
public static IEnumerable<KeyValuePair<string, Type>> ByAreaName(
this IEnumerable<KeyValuePair<string, Type>> query, string areaName)
{
string areaNameToFind = string.Format(CultureInfo.CurrentCulture, ".{0}.", areaName);
return query.Where(x => x.Key.IndexOf(areaNameToFind, StringComparison.OrdinalIgnoreCase) != -1);
}
/// <summary>
/// 获取不包含区域名的键值对
/// </summary>
/// <param name="query">键值对列表</param>
/// <returns></returns>
public static IEnumerable<KeyValuePair<string, Type>> WithoutAreaName(
this IEnumerable<KeyValuePair<string, Type>> query)
{
return query.Where(x => x.Key.IndexOf(".areas.", StringComparison.OrdinalIgnoreCase) == -1);
}
/// <summary>
/// 根据控制器名获取键值对
/// </summary>
/// <param name="query">键值对列表</param>
/// <param name="controllerName">控制器名</param>
/// <returns></returns>
public static IEnumerable<KeyValuePair<string, Type>> ByControllerName(
this IEnumerable<KeyValuePair<string, Type>> query, string controllerName)
{
string controllerNameToFind = string.Format(CultureInfo.InvariantCulture, ".{0}{1}", controllerName,
DefaultHttpControllerSelector.ControllerSuffix);
return query.Where(x => x.Key.EndsWith(controllerNameToFind, StringComparison.OrdinalIgnoreCase));
}
}
}

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
namespace SwashbuckleEx.WebApiTest.Selectors
{
/// <summary>
/// 扩展自DefaultHttpControllerSelector类的控制器选择器目前在用
/// </summary>
public class NamespaceHttpControllerSelector : DefaultHttpControllerSelector
{
private const string NamespaceRouteVariableName = "namespaces";
private readonly HttpConfiguration _configuration;
private readonly Lazy<ConcurrentDictionary<string, Type>> _apiControllerCache;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="configuration"></param>
public NamespaceHttpControllerSelector(HttpConfiguration configuration)
: base(configuration)
{
_configuration = configuration;
_apiControllerCache = new Lazy<ConcurrentDictionary<string, Type>>(new Func<ConcurrentDictionary<string, Type>>(InitializeApiControllerCache));
}
/// <summary>
/// 初始化ApiController实例
/// </summary>
/// <returns></returns>
private ConcurrentDictionary<string, Type> InitializeApiControllerCache()
{
IAssembliesResolver assembliesResolver = this._configuration.Services.GetAssembliesResolver();
var types = this._configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(assembliesResolver).ToDictionary(t => t.FullName, t => t);
return new ConcurrentDictionary<string, Type>(types);
}
/// <summary>
/// 获取Controller全名
/// </summary>
/// <param name="request"></param>
/// <param name="controllerName"></param>
public IEnumerable<string> GetControllerFullName(HttpRequestMessage request, string controllerName)
{
object namespaceName;
var data = request.GetRouteData();
IEnumerable<string> keys = _apiControllerCache.Value.ToDictionary<KeyValuePair<string, Type>, string, Type>(t => t.Key, t => t.Value, StringComparer.CurrentCultureIgnoreCase).Keys.ToList();
if (!data.Values.TryGetValue(NamespaceRouteVariableName, out namespaceName))
{
return from k in keys
where k.EndsWith(string.Format(".{0}{1}", controllerName,
DefaultHttpControllerSelector.ControllerSuffix), StringComparison.CurrentCultureIgnoreCase)
select k;
}
string[] namespaces = (string[])namespaceName;
return from n in namespaces
join k in keys on string.Format("{0}.{1}{2}", n, controllerName,
DefaultHttpControllerSelector.ControllerSuffix).ToLower() equals k.ToLower()
select k;
}
/// <summary>
/// 获取Controller
/// </summary>
/// <param name="request"></param>
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
Type type;
if (request == null)
{
throw new ArgumentNullException("request");
}
string controllerName = this.GetControllerName(request);
if (string.IsNullOrEmpty(controllerName))
{
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("无法通过API路由匹配到您所请求的URI '{0}'", new object[] { request.RequestUri })));
}
IEnumerable<string> fullNames = GetControllerFullName(request, controllerName);
if (fullNames.Count() == 0)
{
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("无法通过API路由匹配到您所请求的URI '{0}'", new object[] { request.RequestUri })));
}
if (this._apiControllerCache.Value.TryGetValue(fullNames.First(), out type))
{
return new HttpControllerDescriptor(_configuration, controllerName, type);
}
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("无法通过API路由匹配到您所请求的URI '{0}'", new object[] { request.RequestUri })));
}
/// <summary>
/// 获取ControllerMapping
/// </summary>
/// <returns></returns>
public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
{
return _apiControllerCache.Value.ToDictionary(c => c.Key, c => new HttpControllerDescriptor(_configuration, c.Value.Name.Substring(0, c.Value.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length), c.Value), StringComparer.OrdinalIgnoreCase);
}
}
}

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Description;
using System.Web.Http.Dispatcher;
using Swashbuckle.Swagger;
namespace SwashbuckleEx.WebApiTest.Selectors
{
/// <summary>
/// Swagger区域文档过滤器
/// </summary>
public class SwaggerAreasSupportDocumentFilter:IDocumentFilter
{
/// <summary>
/// 申请处理
/// </summary>
/// <param name="swaggerDoc"></param>
/// <param name="schemaRegistry"></param>
/// <param name="apiExplorer"></param>
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
IDictionary<string,PathItem> replacePaths=new ConcurrentDictionary<string,PathItem>();
foreach (var item in swaggerDoc.paths)
{
string key = item.Key;
var value = item.Value;
var keys = key.Split('/');
if (keys[3].IndexOf('.')!=-1)
{
// 区域路径
string areasName = keys[2];
string namespaceFullName = keys[3];
var directoryNames = namespaceFullName.Split('.');
string namespaceName = directoryNames[3];
if (areasName.Equals(namespaceName, StringComparison.OrdinalIgnoreCase))
{
string controllerName = directoryNames[5];
replacePaths.Add(
item.Key.Replace(namespaceFullName,
controllerName.Substring(0,
controllerName.Length - DefaultHttpControllerSelector.ControllerSuffix.Length)),
value);
}
}
else if(keys[2].IndexOf('.')!=-1)
{
// 基础路径
string namespaceFullName = keys[2];
var directoryNames = namespaceFullName.Split('.');
bool isControllers = directoryNames[2].Equals("Controllers", StringComparison.OrdinalIgnoreCase);
string controllerName = directoryNames[3];
if (isControllers)
{
replacePaths.Add(
item.Key.Replace(namespaceFullName,
controllerName.Substring(0,
controllerName.Length - DefaultHttpControllerSelector.ControllerSuffix.Length)), value);
}
}
}
swaggerDoc.paths = replacePaths;
}
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Owin;
using Owin;
using SwashbuckleEx.WebApiTest;
[assembly:OwinStartup(typeof(Startup))]
namespace SwashbuckleEx.WebApiTest
{
public class Startup
{
/// <summary>
/// 配置
/// </summary>
/// <param name="app"></param>
public void Configuration(IAppBuilder app)
{
}
}
}

View File

@@ -0,0 +1,216 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
<Import Project="..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{42BFF3DE-68B0-4DD0-96E1-2BF29975F522}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SwashbuckleEx.WebApiTest</RootNamespace>
<AssemblyName>SwashbuckleEx.WebApiTest</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<UseIISExpress>true</UseIISExpress>
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<Use64BitIISExpress />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\SwashbuckleEx.WebApiTest.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Owin, Version=3.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.3.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=3.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.Host.SystemWeb.3.1.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Swashbuckle.WebHost, Version=1.0.8.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\SwashbuckleEx.1.0.8.0\lib\net45\Swashbuckle.WebHost.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Core" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
<Reference Include="WebActivatorEx, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7b26dc2a43f6a0d4, processorArchitecture=MSIL">
<HintPath>..\packages\WebActivatorEx.2.2.0\lib\net40\WebActivatorEx.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http.WebHost">
<HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="Global.asax" />
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup>
<Compile Include="App_Start\SimpleCorsHandler.cs" />
<Compile Include="App_Start\SwaggerConfig.cs" />
<Compile Include="App_Start\WebApiConfig.cs" />
<Compile Include="Areas\Admin\Controllers\TestAController.cs" />
<Compile Include="Areas\Client\Controllers\TestAController.cs" />
<Compile Include="Areas\Extensions.cs" />
<Compile Include="Controllers\TestAController.cs" />
<Compile Include="Extensions\AddUploadOperationFilter.cs" />
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="Models\UserInfo.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Selectors\AreaHttpControllerSelector.cs" />
<Compile Include="Selectors\ClassifiedHttpControllerSelector.cs" />
<Compile Include="Selectors\ControllerTypeSpecifications.cs" />
<Compile Include="Selectors\NamespaceHttpControllerSelector.cs" />
<Compile Include="Selectors\SwaggerAreasSupportDocumentFilter.cs" />
<Compile Include="Extensions\UploadAttribute.cs" />
<Compile Include="Startup.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="packages.config" />
<None Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
</None>
<None Include="Web.Release.config">
<DependentUpon>Web.config</DependentUpon>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Swashbuckle.Core\Swashbuckle.Core.csproj">
<Project>{15e76579-e0c4-4cd4-9083-0e04f9fd531d}</Project>
<Name>Swashbuckle.Core</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>24067</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:24067/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.1.0.0\build\Microsoft.Net.Compilers.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\build\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 有关使用 web.config 转换的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--
在下例中“SetAttributes”转换将更改
“connectionString”的值以仅在“Match”定位器
找到值为“MyDB”的特性“name”时使用“ReleaseSQLServer”。
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<system.web>
<!--
在下例中“Replace”转换将替换
web.config 文件的整个 <customErrors> 节。
请注意,由于
在 <system.web> 节点下仅有一个 customErrors 节因此不需要使用“xdt:Locator”特性。
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 有关使用 web.config 转换的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--
在下例中“SetAttributes”转换将更改
“connectionString”的值以仅在“Match”定位器
找到值为“MyDB”的特性“name”时使用“ReleaseSQLServer”。
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
<!--
在下例中“Replace”转换将替换
web.config 文件的整个 <customErrors> 节。
请注意,由于
在 <system.web> 节点下仅有一个 customErrors 节因此不需要使用“xdt:Locator”特性。
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
有关如何配置 ASP.NET 应用程序的详细信息,请访问
http://go.microsoft.com/fwlink/?LinkId=301879
-->
<configuration>
<appSettings></appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5"/>
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
<remove name="OPTIONSVerbHandler"/>
<remove name="TRACEVerbHandler"/>
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs"
type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701"/>
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
</compilers>
</system.codedom>
</configuration>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client.zh-Hans" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core.zh-Hans" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost.zh-Hans" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net45" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.0" targetFramework="net45" />
<package id="Microsoft.Net.Compilers" version="1.0.0" targetFramework="net45" developmentDependency="true" />
<package id="Microsoft.Owin" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Host.SystemWeb" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="SwashbuckleEx" version="1.0.8.0" targetFramework="net45" />
<package id="SwashbuckleEx.Core" version="1.0.8.0" targetFramework="net45" />
<package id="WebActivatorEx" version="2.2.0" targetFramework="net45" />
</packages>