对请求进行路由解析以及消息处理管道进行处理后,最后可以从HttpRequestMessage对象的属性字典中获取解析的路由数据,后边我们就可以根据其进行HttpController的创建,从前边几篇可知道,消息处理管道的末端即最后一个处理器HttpRoutingDispatcher会把消息派送给其一个内部处理器HttpControllerDispatcher进行HttpController的创建。这篇先介绍下HttpController,先熟悉下相关类,后边都会用到,后边会把这些类联系起来。

  关注点:

  • 熟悉下各类成员及关系,基本都有注释
  • 主要看ApiController抽象类的方法,项目中创建的控制器都继承它,很多方法都可以直接使用,核心逻辑方法是ExecuteAsync,创建控制器对象后,会调用ExecuteAsync方法,进行后续操作,由于还没讲控制器的创建,里边的逻辑以后再细说

一、涉及的类及源码分析

1、IHttpController

  我们创建的Web API项目中的所有的Controller最后都要继承该接口,如ProductController先继承ApiController,ApiController再继承IHttpController,接口定义如下,就一个方法ExecuteAsync方法,主要是一个参数HttpControllerContext,其具体见下一个类。

       

  

  

2、HttpControllerContext

  表示执行HttpController的上下文,作为IHttpController接口的ExecuteAsync方法的参数,主要包含以下五个属性,前三个可以在构造函数里指定,也可以直接赋值

  HttpConfiguration  全局配置

  IHttpRouteData  解析的路由数据

  HttpRequestMessage  表示当前请求

  HttpControIlerDesciptor  描述HttpController

  HttpControIler 控制器对象

  这个类没什么逻辑,只是在构造函数可以创建一个RequestContext

  1. _requestContext = new HttpRequestContext
  2. {
  3. Configuration = configuration,
  4. RouteData = routeData
  5. };
  1. public class HttpControllerContext
  2. {
  3. private HttpRequestContext _requestContext;
  4. private HttpRequestMessage _request;
  5. private HttpControllerDescriptor _controllerDescriptor;
  6. private IHttpController _controller;
  7.  
  8. public HttpControllerContext(HttpRequestContext requestContext, HttpRequestMessage request,
  9. HttpControllerDescriptor controllerDescriptor, IHttpController controller)
  10. {
  11. if (requestContext == null)
  12. {
  13. throw Error.ArgumentNull("requestContext");
  14. }
  15.  
  16. if (request == null)
  17. {
  18. throw Error.ArgumentNull("request");
  19. }
  20.  
  21. if (controllerDescriptor == null)
  22. {
  23. throw Error.ArgumentNull("controllerDescriptor");
  24. }
  25.  
  26. if (controller == null)
  27. {
  28. throw Error.ArgumentNull("controller");
  29. }
  30.  
  31. _requestContext = requestContext;
  32. _request = request;
  33. _controllerDescriptor = controllerDescriptor;
  34. _controller = controller;
  35. }
  36.  
  37. public HttpControllerContext(HttpConfiguration configuration, IHttpRouteData routeData,
  38. HttpRequestMessage request)
  39. {
  40. if (configuration == null)
  41. {
  42. throw Error.ArgumentNull("configuration");
  43. }
  44.  
  45. if (routeData == null)
  46. {
  47. throw Error.ArgumentNull("routeData");
  48. }
  49.  
  50. if (request == null)
  51. {
  52. throw Error.ArgumentNull("request");
  53. }
  54.  
  55. //requestContext包含了Configuration和RouteData
  56. _requestContext = new HttpRequestContext
  57. {
  58. Configuration = configuration,
  59. RouteData = routeData
  60. };
  61. _request = request;
  62. }
  63.  
  64. public HttpControllerContext()
  65. {
  66.  
  67. _requestContext = new HttpRequestContext();
  68. }
  69.  
  70. public HttpConfiguration Configuration
  71. {
  72. get
  73. {
  74. return _requestContext.Configuration;
  75. }
  76. set
  77. {
  78. if (value == null)
  79. {
  80. throw Error.PropertyNull();
  81. }
  82.  
  83. _requestContext.Configuration = value;
  84. }
  85. }
  86. public HttpControllerDescriptor ControllerDescriptor
  87. {
  88. get { return _controllerDescriptor; }
  89. set
  90. {
  91. if (value == null)
  92. {
  93. throw Error.PropertyNull();
  94. }
  95.  
  96. _controllerDescriptor = value;
  97. }
  98. }
  99. public IHttpController Controller
  100. {
  101. get { return _controller; }
  102. set
  103. {
  104. if (value == null)
  105. {
  106. throw Error.PropertyNull();
  107. }
  108.  
  109. _controller = value;
  110. }
  111. }
  112.  
  113. public HttpRequestMessage Request
  114. {
  115. get { return _request; }
  116. set
  117. {
  118. if (value == null)
  119. {
  120. throw Error.PropertyNull();
  121. }
  122.  
  123. _request = value;
  124. }
  125. }
  126.  
  127. public HttpRequestContext RequestContext
  128. {
  129. get { return _requestContext; }
  130. set
  131. {
  132. if (value == null)
  133. {
  134. throw Error.PropertyNull();
  135. }
  136.  
  137. _requestContext = value;
  138. }
  139. }
  140.  
  141. public IHttpRouteData RouteData
  142. {
  143. get { return _requestContext.RouteData; }
  144. set
  145. {
  146. if (value == null)
  147. {
  148. throw Error.PropertyNull();
  149. }
  150.  
  151. _requestContext.RouteData = value;
  152. }
  153. }
  154. }

3、HttpControllerDescriptor

  描述HttpController对象,封装了HttpController元数据,系统就是根据HttpControllerDescriptor创建Controller的;主要有以下三个属性,可以在构造函数指定,也可以直接赋值。

  HttpConfiguration 全局配置

  ControllerName  描述HttpCoutroller的控制器名称

  ControllerType 描述HttpCoutroller的Type

  还有个特殊的属性,类似HttpRequestMessage和HttpConfiguration类似的设计,可以添加任何对象到该属性

  Properties 类型为ConcurrentDictionary(object, object)

  另外,有以下主要方法:

    IHttpController CreateController(HttpRequestMessage request)   创建Controller核心方法,主要逻辑都在这

  Collection<T> GetCustomAttributes<T>() where T: class  获取定义在控制器上的自定义属性

  Collection<T> GetCustomAttributes(bool inherit)where T: class  同上

  virtual Collection<IFilter> GetFilters() 获取定在在控制器上的过滤器

  1. public class HttpControllerDescriptor
  2. {
  3. //附加任何对象到该字典属性
  4. private readonly ConcurrentDictionary<object, object> _properties = new ConcurrentDictionary<object, object>();
  5.  
  6. private HttpConfiguration _configuration;
  7.  
  8. private string _controllerName;
  9. private Type _controllerType;
  10.  
  11. //缓存用
  12. private object[] _attributeCache;
  13. private object[] _declaredOnlyAttributeCache;
  14.  
  15. //后边文章介绍,解析出ControllerType时候会调用该构造函数创建HttpControllerDescriptor
  16. public HttpControllerDescriptor(HttpConfiguration configuration, string controllerName, Type controllerType)
  17. {
  18. if (configuration == null)
  19. {
  20. throw Error.ArgumentNull("configuration");
  21. }
  22.  
  23. if (controllerName == null)
  24. {
  25. throw Error.ArgumentNull("controllerName");
  26. }
  27.  
  28. if (controllerType == null)
  29. {
  30. throw Error.ArgumentNull("controllerType");
  31. }
  32.  
  33. _configuration = configuration;
  34. _controllerName = controllerName;
  35. _controllerType = controllerType;
  36. //构造函数里直接调用Initialize
  37.  
  38. Initialize();
  39. }
  40.  
  41. //默认构造函数,单元测试用
  42. public HttpControllerDescriptor()
  43. {
  44. }
  45.  
  46. //默认构造函数,单元测试用
  47. internal HttpControllerDescriptor(HttpConfiguration configuration)
  48. {
  49. Initialize(configuration);
  50. }
  51.  
  52. /// <summary>
  53. /// 附加任何对象到该字典属性
  54. /// </summary>
  55. public virtual ConcurrentDictionary<object, object> Properties
  56. {
  57. get { return _properties; }
  58. }
  59.  
  60. public HttpConfiguration Configuration
  61. {
  62. get { return _configuration; }
  63. set
  64. {
  65. if (value == null)
  66. {
  67. throw Error.PropertyNull();
  68. }
  69. _configuration = value;
  70. }
  71. }
  72.  
  73. //控制器名称
  74. public string ControllerName
  75. {
  76. get { return _controllerName; }
  77. set
  78. {
  79. if (value == null)
  80. {
  81. throw Error.PropertyNull();
  82. }
  83. _controllerName = value;
  84. }
  85. }
  86.  
  87. //控制器类型
  88. public Type ControllerType
  89. {
  90. get { return _controllerType; }
  91. set
  92. {
  93. if (value == null)
  94. {
  95. throw Error.PropertyNull();
  96. }
  97. _controllerType = value;
  98. }
  99. }
  100.  
  101. //主要方法 根据HttpRequestMessage创建一个IHttpController
  102. public virtual IHttpController CreateController(HttpRequestMessage request)
  103. {
  104. if (request == null)
  105. {
  106. throw Error.ArgumentNull("request");
  107. }
  108.  
  109. //先从ServicesContainer获取默认的IHttpControllerActivator
  110. IHttpControllerActivator activator = Configuration.Services.GetHttpControllerActivator();
  111. //调用IHttpControllerActivator的Create方法,创建,这个后一篇会说到
  112. IHttpController instance = activator.Create(request, this, ControllerType);
  113. return instance;
  114. }
  115.  
  116. //描述符对应的控制器定义的过滤器列表
  117. public virtual Collection<IFilter> GetFilters()
  118. {
  119. return GetCustomAttributes<IFilter>();
  120. }
  121.  
  122. //获取泛型的自定义特性的集合,对应控制器上定义的
  123. public virtual Collection<T> GetCustomAttributes<T>() where T : class
  124. {
  125. return GetCustomAttributes<T>(inherit: true);
  126. }
  127.  
  128. //获取泛型的自定义特性的集合,对应控制器上定义的
  129.  
  130. public virtual Collection<T> GetCustomAttributes<T>(bool inherit) where T : class
  131. {
  132. object[] attributes;
  133. //反射获取自定义特性很慢,所以使用缓存_attributeCache,第二次开始,就直接从其获取
  134. //inherit决定是否要去控制器类型继承结构中去找所有特性
  135. if (inherit)
  136. {
  137.  
  138. if (_attributeCache == null)
  139. {
  140. _attributeCache = ControllerType.GetCustomAttributes(inherit: true);
  141. }
  142. attributes = _attributeCache;
  143. }
  144. else
  145. {
  146. if (_declaredOnlyAttributeCache == null)
  147. {
  148. //是从ControllerType属性上去寻找特性的
  149. _declaredOnlyAttributeCache = ControllerType.GetCustomAttributes(inherit: false);
  150. }
  151. attributes = _declaredOnlyAttributeCache;
  152. }
  153.  
  154. return new Collection<T>(TypeHelper.OfType<T>(attributes));
  155. }
  156.  
  157. private void Initialize()
  158. {
  159. InvokeAttributesOnControllerType(this, ControllerType);
  160. }
  161.  
  162. //先略过
  163. private static void InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type)
  164. {
  165. Contract.Assert(controllerDescriptor != null);
  166.  
  167. if (type == null)
  168. {
  169. return;
  170. }
  171.  
  172. InvokeAttributesOnControllerType(controllerDescriptor, type.BaseType);
  173.  
  174. object[] attrs = type.GetCustomAttributes(inherit: false);
  175. foreach (object attr in attrs)
  176. {
  177. var controllerConfig = attr as IControllerConfiguration;
  178. if (controllerConfig != null)
  179. {
  180. var originalConfig = controllerDescriptor.Configuration;
  181. var controllerSettings = new HttpControllerSettings(originalConfig);
  182. controllerConfig.Initialize(controllerSettings, controllerDescriptor);
  183. controllerDescriptor.Configuration = HttpConfiguration.ApplyControllerSettings(controllerSettings, originalConfig);
  184. }
  185. }
  186. }
  187. }

4、ApiController

  WebAPI项目创建的HttpController类型默认继承ApiController,ApiController又继承自IHttpController和IDisposable

   HttpControllerContext ControllerContext 表示执行当前ApiController上下文
  HttpConfiguration Configration 全局配置 同 HttpControllerContext
  HttpRequestMessage Request 请求消息 同 HttpControllerContext
  HttpRouteData  RouteData  路由解析数据 同 HttpControllerContext
  ModelstateDictionary Modelstate  包含其中的数据会被以Model绑定的形式绑定到目标Aotion方法的对应的参数

  UrlHelper Url  可以根据注册的HttpRoute和提供的路由变量生成—个完整的URL   
  IPrincipal User 返回当前线程的Principal ,前几篇中HttpServer在SendAsync方法执行过程中,如果当前线程中的当前线程的Principal为Null,创建一个空的GenericPrincipaI对象作为当前线程的匿名Principal。

  主要方法有以下几个:

  virtual Task<HttpRequsetMessage> ExecuteAsync(HttpControllerContext controllerContext,...)  实现IHttpController接口

  virtual void Initialize(HttpControllerContext  controllerContext) 受保护方法

  //资源回收

  void Dispose()
  virtual void Dispose(bool disposing)

  另外,特别注意,ApiController不能重复使用,每次请求都会使用一个新的HttpController来处理请求,ExecuteAsync方法的时候发现当前的ApiController已经处于“初始化”的状态,系统会直接抛出一个InvaIidationException异常。

  1. public abstract class ApiController : IHttpController, IDisposable
  2. {
  3. private HttpActionContext _actionContext = new HttpActionContext();
  4. private bool _initialized;
  5.  
  6. //获取HttpConfiguration
  7. //setter 单元测试用
  8. public HttpConfiguration Configuration
  9. {
  10. get { return ControllerContext.Configuration; }
  11. set { ControllerContext.Configuration = value; }
  12. }
  13.  
  14. //获取HttpControllerContext
  15. //setter 单元测试用
  16. public HttpControllerContext ControllerContext
  17. {
  18. get
  19. {
  20. // unit test only
  21. if (ActionContext.ControllerContext == null)
  22. {
  23. ActionContext.ControllerContext = new HttpControllerContext
  24. {
  25. RequestContext = new RequestBackedHttpRequestContext()
  26. };
  27. }
  28. return ActionContext.ControllerContext;
  29. }
  30. set
  31. {
  32. if (value == null)
  33. {
  34. throw Error.PropertyNull();
  35. }
  36.  
  37. ActionContext.ControllerContext = value;
  38. }
  39. }
  40.  
  41. //获取HttpRequestMessage
  42. //setter 单元测试用
  43. public HttpActionContext ActionContext
  44. {
  45. get { return _actionContext; }
  46. set
  47. {
  48. if (value == null)
  49. {
  50. throw Error.PropertyNull();
  51. }
  52. _actionContext = value;
  53. }
  54. }
  55.  
  56. //在模型绑定之后获取ModelState,绑定之前是空的,模型绑定以后再说
  57. public ModelStateDictionary ModelState
  58. {
  59. get
  60. {
  61. return ActionContext.ModelState;
  62. }
  63. }
  64.  
  65. //获取HttpRequestMessage
  66. //setter 单元测试用
  67. public HttpRequestMessage Request
  68. {
  69. get
  70. {
  71. return ControllerContext.Request;
  72. }
  73. set
  74. {
  75. if (value == null)
  76. {
  77. throw Error.PropertyNull();
  78. }
  79.  
  80. HttpRequestContext contextOnRequest = value.GetRequestContext();
  81. HttpRequestContext contextOnController = RequestContext;
  82.  
  83. if (contextOnRequest != null && contextOnRequest != contextOnController)
  84. {
  85. // Prevent unit testers from setting conflicting requests contexts.
  86. throw new InvalidOperationException(SRResources.RequestContextConflict);
  87. }
  88.  
  89. ControllerContext.Request = value;
  90. value.SetRequestContext(contextOnController);
  91.  
  92. RequestBackedHttpRequestContext requestBackedContext =
  93. contextOnController as RequestBackedHttpRequestContext;
  94.  
  95. if (requestBackedContext != null)
  96. {
  97. requestBackedContext.Request = value;
  98. }
  99. }
  100. }
  101.  
  102. //获取HttpRequestContext
  103. //setter 单元测试用
  104. public HttpRequestContext RequestContext
  105. {
  106. get
  107. {
  108. return ControllerContext.RequestContext;
  109. }
  110. set
  111. {
  112. if (value == null)
  113. {
  114. throw Error.PropertyNull();
  115. }
  116.  
  117. HttpRequestContext oldContext = ControllerContext.RequestContext;
  118. HttpRequestMessage request = Request;
  119.  
  120. if (request != null)
  121. {
  122. HttpRequestContext contextOnRequest = request.GetRequestContext();
  123.  
  124. if (contextOnRequest != null && contextOnRequest != oldContext && contextOnRequest != value)
  125. {
  126. // Prevent unit testers from setting conflicting requests contexts.
  127. throw new InvalidOperationException(SRResources.RequestContextConflict);
  128. }
  129.  
  130. request.SetRequestContext(value);
  131. }
  132.  
  133. ControllerContext.RequestContext = value;
  134. }
  135. }
  136.  
  137. //获取UrlHelper用来对其他APIS生成URLS
  138. //setter 单元测试用
  139. public UrlHelper Url
  140. {
  141. get { return RequestContext.Url; }
  142. set { RequestContext.Url = value; }
  143. }
  144.  
  145. //获取或设置当前请求的Principal
  146. //setter 单元测试用
  147. public IPrincipal User
  148. {
  149. get { return RequestContext.Principal; }
  150. set { RequestContext.Principal = value; }
  151. }
  152.  
  153. //主要方法,创建控制器对象后,会调用ExecuteAsync方法,进行后续操作,由于还没讲控制器的创建,里边的逻辑以后再细说
  154. public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
  155. {
  156. if (_initialized)
  157. {
  158. // 如果已经创建过该实例,就抛出异常,一个控制器实例,多次请求不能重复使用
  159. throw Error.InvalidOperation(SRResources.CannotSupportSingletonInstance, typeof(ApiController).Name, typeof(IHttpControllerActivator).Name);
  160. }
  161.  
  162. Initialize(controllerContext);
  163.  
  164. if (Request != null)
  165. {
  166. //先注册到待销毁集合,待请求完成后一起销毁改控制器实例
  167. Request.RegisterForDispose(this);
  168. }
  169.  
  170. HttpControllerDescriptor controllerDescriptor = controllerContext.ControllerDescriptor;
  171. ServicesContainer controllerServices = controllerDescriptor.Configuration.Services;
  172. //选择Action
  173. HttpActionDescriptor actionDescriptor = controllerServices.GetActionSelector().SelectAction(controllerContext);
  174. ActionContext.ActionDescriptor = actionDescriptor;
  175. if (Request != null)
  176. {
  177. Request.SetActionDescriptor(actionDescriptor);
  178. }
  179.  
  180. FilterGrouping filterGrouping = actionDescriptor.GetFilterGrouping();
  181.  
  182. //ActionFilters
  183. IActionFilter[] actionFilters = filterGrouping.ActionFilters;
  184. //身份认证过滤器
  185. IAuthenticationFilter[] authenticationFilters = filterGrouping.AuthenticationFilters;
  186. //授权过滤器
  187. IAuthorizationFilter[] authorizationFilters = filterGrouping.AuthorizationFilters;
  188. //ExceptionFilters
  189. IExceptionFilter[] exceptionFilters = filterGrouping.ExceptionFilters;
  190.  
  191. IHttpActionResult result = new ActionFilterResult(actionDescriptor.ActionBinding, ActionContext,
  192. controllerServices, actionFilters);
  193. if (authorizationFilters.Length > )
  194. {
  195. result = new AuthorizationFilterResult(ActionContext, authorizationFilters, result);
  196. }
  197. if (authenticationFilters.Length > )
  198. {
  199. result = new AuthenticationFilterResult(ActionContext, this, authenticationFilters, result);
  200. }
  201. if (exceptionFilters.Length > )
  202. {
  203. IExceptionLogger exceptionLogger = ExceptionServices.GetLogger(controllerServices);
  204. IExceptionHandler exceptionHandler = ExceptionServices.GetHandler(controllerServices);
  205. result = new ExceptionFilterResult(ActionContext, exceptionFilters, exceptionLogger, exceptionHandler,
  206. result);
  207. }
  208. //执行IHttpActionResult的ExecuteAsync
  209. return result.ExecuteAsync(cancellationToken);
  210. }
  211.  
  212. //验证entity,并把验证错误添加到ModelState
  213. public void Validate<TEntity>(TEntity entity)
  214. {
  215. Validate(entity, keyPrefix: String.Empty);
  216. }
  217.  
  218. //验证entity,并把验证错误添加到ModelState
  219. public void Validate<TEntity>(TEntity entity, string keyPrefix)
  220. {
  221. if (Configuration == null)
  222. {
  223. throw Error.InvalidOperation(SRResources.TypePropertyMustNotBeNull, typeof(ApiController).Name, "Configuration");
  224. }
  225.  
  226. IBodyModelValidator validator = Configuration.Services.GetBodyModelValidator();
  227. if (validator != null)
  228. {
  229. ModelMetadataProvider metadataProvider = Configuration.Services.GetModelMetadataProvider();
  230. Contract.Assert(metadataProvider != null, "GetModelMetadataProvider throws on null.");
  231.  
  232. validator.Validate(entity, typeof(TEntity), metadataProvider, ActionContext, keyPrefix);
  233. }
  234. }
  235.  
  236. //创建一个400 Bad Request,项目中的Controller里可以直接使用
  237. protected internal virtual BadRequestResult BadRequest()
  238. {
  239. return new BadRequestResult(this);
  240. }
  241.  
  242. //根据message 创建一个400 Bad Request,项目中的Controller里可以直接使用
  243. protected internal virtual BadRequestErrorMessageResult BadRequest(string message)
  244. {
  245. return new BadRequestErrorMessageResult(message, this);
  246. }
  247.  
  248. //根据指定的modelState创建一个 400 Bad Request.
  249. protected internal virtual InvalidModelStateResult BadRequest(ModelStateDictionary modelState)
  250. {
  251. return new InvalidModelStateResult(modelState, this);
  252. }
  253.  
  254. //创建一个 409 Conflict
  255. protected internal virtual ConflictResult Conflict()
  256. {
  257. return new ConflictResult(this);
  258. }
  259.  
  260. /// <summary>创建一个内容协商结果响应</summary>
  261. /// <typeparam name="T">主体内容中的数据类型</typeparam>
  262. /// <param name="statusCode">响应状态码</param>
  263. /// <param name="value">在主体中要协商和格式化的数据</param>
  264. /// <returns>A <see cref="NegotiatedContentResult{T}"/> with the specified values.</returns>
  265. protected internal virtual NegotiatedContentResult<T> Content<T>(HttpStatusCode statusCode, T value)
  266. {
  267. return new NegotiatedContentResult<T>(statusCode, value, this);
  268. }
  269.  
  270. /// <summary>创建一个指定格式化的内容响应</summary>
  271. /// <typeparam name="T">主体内容中的数据类型</typeparam>
  272. /// <param name="statusCode">响应状态码</param>
  273. /// <param name="value">在主体中要协商和格式化的数据</param>
  274. /// <param name="formatter">格式化器</param>
  275. /// <returns>A <see cref="FormattedContentResult{T}"/> with the specified values.</returns>
  276. protected internal FormattedContentResult<T> Content<T>(HttpStatusCode statusCode, T value,
  277. MediaTypeFormatter formatter)
  278. {
  279. return Content(statusCode, value, formatter, (MediaTypeHeaderValue)null);
  280. }
  281.  
  282. /// <summary>创建一个指定媒体类型的格式化的内容响应</summary>
  283. /// <typeparam name="T">主体内容中的数据类型</typeparam>
  284. /// <param name="statusCode">响应状态码</param>
  285. /// <param name="value">在主体中要协商和格式化的数据</param>
  286. /// <param name="formatter">格式化器</param>
  287. /// <param name="mediaType">媒体类型</param>
  288. /// <returns>A <see cref="FormattedContentResult{T}"/> with the specified values.</returns>
  289. protected internal FormattedContentResult<T> Content<T>(HttpStatusCode statusCode, T value,
  290. MediaTypeFormatter formatter, string mediaType)
  291. {
  292. return Content(statusCode, value, formatter, new MediaTypeHeaderValue(mediaType));
  293. }
  294.  
  295. /// <summary>创建一个指定媒体类型的格式化的内容响应</summary>
  296. /// <typeparam name="T">主体内容中的数据类型</typeparam>
  297. /// <param name="statusCode">响应状态码</param>
  298. /// <param name="value">在主体中要协商和格式化的数据</param>
  299. /// <param name="formatter">格式化器</param>
  300. /// <param name="mediaType">媒体类型</param>
  301. /// <returns>A <see cref="FormattedContentResult{T}"/> with the specified values.</returns>
  302. protected internal virtual FormattedContentResult<T> Content<T>(HttpStatusCode statusCode, T value,
  303. MediaTypeFormatter formatter, MediaTypeHeaderValue mediaType)
  304. {
  305. return new FormattedContentResult<T>(statusCode, value, formatter, mediaType, this);
  306. }
  307.  
  308. /// <summary>
  309. /// 创建一个201 Created 响应Created
  310. /// </summary>
  311. /// <typeparam name="T">The type of content in the entity body.</typeparam>
  312. /// <param name="location">
  313. /// The location at which the content has been created. Must be a relative or absolute URL.
  314. /// </param>
  315. /// <param name="content">The content value to negotiate and format in the entity body.</param>
  316. /// <returns>A <see cref="CreatedNegotiatedContentResult{T}"/> with the specified values.</returns>
  317. protected internal CreatedNegotiatedContentResult<T> Created<T>(string location, T content)
  318. {
  319. if (location == null)
  320. {
  321. throw new ArgumentNullException("location");
  322. }
  323.  
  324. return Created<T>(new Uri(location, UriKind.RelativeOrAbsolute), content);
  325. }
  326.  
  327. /// <summary>
  328. /// 创建一个201 Created 响应Created
  329. /// </summary>
  330. /// <typeparam name="T">The type of content in the entity body.</typeparam>
  331. /// <param name="location">The location at which the content has been created.</param>
  332. /// <param name="content">The content value to negotiate and format in the entity body.</param>
  333. /// <returns>A <see cref="CreatedNegotiatedContentResult{T}"/> with the specified values.</returns>
  334. protected internal virtual CreatedNegotiatedContentResult<T> Created<T>(Uri location, T content)
  335. {
  336. return new CreatedNegotiatedContentResult<T>(location, content, this);
  337. }
  338.  
  339. /// <summary>
  340. /// 创建一个201 Created 响应Created
  341. /// </summary>
  342. /// <typeparam name="T">The type of content in the entity body.</typeparam>
  343. /// <param name="routeName">The name of the route to use for generating the URL.</param>
  344. /// <param name="routeValues">The route data to use for generating the URL.</param>
  345. /// <param name="content">The content value to negotiate and format in the entity body.</param>
  346. /// <returns>A <see cref="CreatedAtRouteNegotiatedContentResult{T}"/> with the specified values.</returns>
  347. protected internal CreatedAtRouteNegotiatedContentResult<T> CreatedAtRoute<T>(string routeName,
  348. object routeValues, T content)
  349. {
  350. return CreatedAtRoute<T>(routeName, new HttpRouteValueDictionary(routeValues), content);
  351. }
  352.  
  353. /// <summary>
  354. /// 创建一个201 Created 响应Created
  355. /// </summary>
  356. /// <typeparam name="T">The type of content in the entity body.</typeparam>
  357. /// <param name="routeName">The name of the route to use for generating the URL.</param>
  358. /// <param name="routeValues">The route data to use for generating the URL.</param>
  359. /// <param name="content">The content value to negotiate and format in the entity body.</param>
  360. /// <returns>A <see cref="CreatedAtRouteNegotiatedContentResult{T}"/> with the specified values.</returns>
  361. protected internal virtual CreatedAtRouteNegotiatedContentResult<T> CreatedAtRoute<T>(string routeName,
  362. IDictionary<string, object> routeValues, T content)
  363. {
  364. return new CreatedAtRouteNegotiatedContentResult<T>(routeName, routeValues, content, this);
  365. }
  366.  
  367. //创建一个 500 Internal Server Error
  368. protected internal virtual InternalServerErrorResult InternalServerError()
  369. {
  370. return new InternalServerErrorResult(this);
  371. }
  372.  
  373. //根据异常创建一个 500 Internal Server Error
  374. protected internal virtual ExceptionResult InternalServerError(Exception exception)
  375. {
  376. return new ExceptionResult(exception, this);
  377. }
  378.  
  379. /// <summary>创建一个 200 OK 响应,主体内容有JSON格式的数据,JsonSerializerSettings 序列化器</summary>
  380. /// <typeparam name="T">主体内容的数据类型</typeparam>
  381. /// <param name="content">序列化到主体部分的内容</param>
  382. /// <returns>A <see cref="JsonResult{T}"/> with the specified value.</returns>
  383. protected internal JsonResult<T> Json<T>(T content)
  384. {
  385. return Json<T>(content, new JsonSerializerSettings());
  386. }
  387.  
  388. /// <summary>创建一个 200 OK 响应,主体内容有JSON格式的数据, UTF8Encoding编码</summary>
  389. /// <typeparam name="T">主体内容的数据类型</typeparam>
  390. /// <param name="content">序列化到主体部分的内容</param>
  391. /// <param name="serializerSettings">序列化器</param>
  392. /// <returns>A <see cref="JsonResult{T}"/> with the specified values.</returns>
  393. protected internal JsonResult<T> Json<T>(T content, JsonSerializerSettings serializerSettings)
  394. {
  395. return Json<T>(content, serializerSettings, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false,
  396. throwOnInvalidBytes: true));
  397. }
  398.  
  399. /// 创建一个 200 OK 响应,主体内容有JSON格式的数据
  400. /// <typeparam name="T">主体内容的数据类型.</typeparam>
  401. /// <param name="content">序列化到主体部分的内容.</param>
  402. /// <param name="serializerSettings">序列化器</param>
  403. /// <param name="encoding">内容编码</param>
  404. /// <returns>A <see cref="JsonResult{T}"/> with the specified values.</returns>
  405. protected internal virtual JsonResult<T> Json<T>(T content, JsonSerializerSettings serializerSettings,
  406. Encoding encoding)
  407. {
  408. return new JsonResult<T>(content, serializerSettings, encoding, this);
  409. }
  410.  
  411. //创建一个 404 Not Found 响应
  412. protected internal virtual NotFoundResult NotFound()
  413. {
  414. return new NotFoundResult(this);
  415. }
  416.  
  417. //创建一个 200 OK 响应
  418. protected internal virtual OkResult Ok()
  419. {
  420. return new OkResult(this);
  421. }
  422.  
  423. //根据指定主体内容创建 OkNegotiatedContentResult(200 OK)
  424. protected internal virtual OkNegotiatedContentResult<T> Ok<T>(T content)
  425. {
  426. return new OkNegotiatedContentResult<T>(content, this);
  427. }
  428.  
  429. //根据指定值创建一个Redirect 302 Found,参数用来生成URL
  430. protected internal virtual RedirectResult Redirect(string location)
  431. {
  432. if (location == null)
  433. {
  434. throw new ArgumentNullException("location");
  435. }
  436.  
  437. return Redirect(new Uri(location));
  438. }
  439.  
  440. //根据指定值创建一个RedirectResult 302 Found,参数用来生成URL
  441. protected internal virtual RedirectResult Redirect(Uri location)
  442. {
  443. return new RedirectResult(location, this);
  444. }
  445.  
  446. //根据指定值创建一个RedirectToRouteResult 302 Found,参数用来生成URL
  447. protected internal RedirectToRouteResult RedirectToRoute(string routeName, object routeValues)
  448. {
  449. return RedirectToRoute(routeName, new HttpRouteValueDictionary(routeValues));
  450. }
  451.  
  452. //根据指定值创建一个RedirectToRouteResult 302 Found,参数用来生成URL
  453. protected internal virtual RedirectToRouteResult RedirectToRoute(string routeName,
  454. IDictionary<string, object> routeValues)
  455. {
  456. return new RedirectToRouteResult(routeName, routeValues, this);
  457. }
  458.  
  459. //根据HttpResponseMessage创建一个ResponseMessageResult
  460. protected internal virtual ResponseMessageResult ResponseMessage(HttpResponseMessage response)
  461. {
  462. return new ResponseMessageResult(response);
  463. }
  464.  
  465. /// 根据指定的HttpStatusCode创建StatusCodeResult
  466. protected internal virtual StatusCodeResult StatusCode(HttpStatusCode status)
  467. {
  468. return new StatusCodeResult(status, this);
  469. }
  470.  
  471. // 根据指定值 创建401 未授权 响应
  472. //challenges 为 The WWW-Authenticate challenges.
  473. protected internal UnauthorizedResult Unauthorized(params AuthenticationHeaderValue[] challenges)
  474. {
  475. return Unauthorized((IEnumerable<AuthenticationHeaderValue>)challenges);
  476. }
  477.  
  478. // 根据指定值 创建401 未授权 响应
  479. //challenges 为 The WWW-Authenticate challenges.
  480. protected internal virtual UnauthorizedResult Unauthorized(IEnumerable<AuthenticationHeaderValue> challenges)
  481. {
  482. return new UnauthorizedResult(challenges, this);
  483. }
  484.  
  485. //标记_initialized = true说明已经被使用,不能重复使用,即同一个控制器实例只能被使用于一次请求
  486. protected virtual void Initialize(HttpControllerContext controllerContext)
  487. {
  488. if (controllerContext == null)
  489. {
  490. throw Error.ArgumentNull("controllerContext");
  491. }
  492.  
  493. _initialized = true;
  494. ControllerContext = controllerContext;
  495. }
  496.  
  497. #region IDisposable
  498.  
  499. public void Dispose()
  500. {
  501. Dispose(true);
  502. GC.SuppressFinalize(this);
  503. }
  504.  
  505. protected virtual void Dispose(bool disposing)
  506. {
  507. }
  508.  
  509. #endregion IDisposable
  510. }

ASP.NET Web API 框架研究 Controller创建 HttpController介绍的更多相关文章

  1. ASP.NET Web API 框架研究 Controller创建 HttpController 类型解析 选择 创建

    上一篇介绍了HttpController的一些细节,接下来说下HttpController 类型解析.选择和创建.生产HttpController实例的生产线如下图: 一.涉及的类及源码分析 涉及的类 ...

  2. ASP.NET Web API 框架研究 Controller创建过程与消息处理管道

    现在我们从代码角度来看下,从消息处理管道末尾是怎么创建出Controller实例的.消息处理管道末端是一个叫HttpRoutingDispatcher的处理器,其内部完成路由后 ,会把消息派送给其内部 ...

  3. ASP.NET Web API 框架研究 Controller实例的销毁

    我们知道项目中创建的Controller,如ProductController都继承自ApiController抽象类,其又实现了接口IDisposable,所以,框架中自动调用Dispose方法来释 ...

  4. ASP.NET Web API 框架研究 ASP.NET Web API 路由

    ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...

  5. ASP.NET Web API 框架研究 Action方法介绍

    在根据请求解析出匹配的Controller类型并创建实例后,要在该Controller类型中的众多Action方法中选择与请求匹配的那一个,并执行,然后返回响应. Action方法,其元数据,主要包括 ...

  6. ASP.NET Web API 框架研究 核心的消息处理管道

    ASP.NET Web API 的核心框架是一个由一组HttpMessageHandler有序组成的双工消息处理管道:寄宿监听到请求接受后,把消息传入该管道经过所有HttpMessageHandler ...

  7. ASP.NET Web API 框架研究 IoC容器 DependencyResolver

    一.概念 1.IoC(Inversion of Control),控制反转 即将依赖对象的创建和维护交给一个外部容器来负责,而不是应用本身.如,在类型A中需要使用类型B的实例,而B的实例的创建不是由A ...

  8. ASP.NET Web API 框架研究 服务容器 ServicesContainer

    ServicesContainer是一个服务的容器,可以理解为—个轻量级的IoC容器,其维护着一个服务接口类型与服务实例之间的映射关系,可以根据服务接口类型获取对应的服务实例.构成ASP.NET We ...

  9. ASP.NET Web API 框架研究 Self Host模式下的消息处理管道

    Self Host模式下的ASP.NET Web API与WCF非常相似,都可以寄宿在任意类型的托管应用程序中,宿主可以是Windows Form .WPF.控制台应用以及Windows Servic ...

随机推荐

  1. Win10传递优化设置技巧

    什么是“传递优化缓存” “传递优化”是微软为了加快Windows更新和Microsoft Store应用更新的下载速度,而在Windows10中引入的一种“自组织分布式本地化缓存”设计,可以在用户电脑 ...

  2. 增加samba用户提示Failed to add entry for user

    1.首先在Ubuntu安装好samba,具体步骤为:安装samba:sudo apt-get install samba安装smbclient:sudo apt-get install 安装smbfs ...

  3. Intellij idea 系列教程之破解方法

    Intellij idea 系列教程之破解方法 Intellij idea 系列教程目录(https://www.cnblogs.com/binarylei/p/10347600.html) 到这个地 ...

  4. Python之线程与进程

    今天我们来了解一下Python的线程和进程的管理机制 首先,我们要了解下线程跟进程的概念: 线程(Thread)是操作系统能够进行运算调度的最小的单位,是一堆cpu的指令.他被包含在进程中,是进程中的 ...

  5. 找不到类SimpleJdbcTemplate ParameterizedRowMapper cannot be resolved

    找不到类SimpleJdbcTemplate 背景 想编译个web应用,原来spring-jdbc.jar用的是Spring 3.1,今天改成用Spring 4.3,报了这个错误. 现象 编译不通过, ...

  6. 【算法】DP解决旅行路径问题

    问题描述 : After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best choice ...

  7. spring学习 五 依赖注入的方式

    依赖注入有两种方式: 1 构造注入,如果<bean>标签下使用<contructor-arg>,则是构造注入 2 setter注入,就是调用setter方法注入,如果<b ...

  8. mybatis学习 九 代理开发

    1.作用: 实现创建一个接口后把mapper.xml由mybatis生成接口的实现类,通过调用接口对象就可以获取 mapper.xml 中编写的 sql. 2.实现步骤: 2.1 创建一个接口 (1) ...

  9. linux代码笔记

    sudo passwd root更新root密码 软件包管理及shell命令_deb软件包管理一_笔记:dpkj -i 安装dpkj -r 移除dpkj -P 全部移除dpkj -L 列出安装清单dj ...

  10. 2018.12.22 spoj7258 Lexicographical Substring Search(后缀自动机)

    传送门 samsamsam基础题. 题意简述:给出一个串,询问第kkk大的本质不同的串. 然而这就是弦论的简化版. 我们把samsamsam建出来然后贪心选择就行了. 代码: #include< ...