對請求進行路由解析以及消息處理管道進行處理后,最后可以從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
_requestContext = new HttpRequestContext
{
Configuration = configuration, RouteData = routeData };
public class HttpControllerContext { private HttpRequestContext _requestContext; private HttpRequestMessage _request; private HttpControllerDescriptor _controllerDescriptor; private IHttpController _controller; public HttpControllerContext(HttpRequestContext requestContext, HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, IHttpController controller) { if (requestContext == null) { throw Error.ArgumentNull("requestContext"); } if (request == null) { throw Error.ArgumentNull("request"); } if (controllerDescriptor == null) { throw Error.ArgumentNull("controllerDescriptor"); } if (controller == null) { throw Error.ArgumentNull("controller"); } _requestContext = requestContext; _request = request; _controllerDescriptor = controllerDescriptor; _controller = controller; } public HttpControllerContext(HttpConfiguration configuration, IHttpRouteData routeData, HttpRequestMessage request) { if (configuration == null) { throw Error.ArgumentNull("configuration"); } if (routeData == null) { throw Error.ArgumentNull("routeData"); } if (request == null) { throw Error.ArgumentNull("request"); } //requestContext包含了Configuration和RouteData _requestContext = new HttpRequestContext { Configuration = configuration, RouteData = routeData }; _request = request; } public HttpControllerContext() { _requestContext = new HttpRequestContext(); } public HttpConfiguration Configuration { get { return _requestContext.Configuration; } set { if (value == null) { throw Error.PropertyNull(); } _requestContext.Configuration = value; } }
public HttpControllerDescriptor ControllerDescriptor { get { return _controllerDescriptor; } set { if (value == null) { throw Error.PropertyNull(); } _controllerDescriptor = value; } }
public IHttpController Controller { get { return _controller; } set { if (value == null) { throw Error.PropertyNull(); } _controller = value; } } public HttpRequestMessage Request { get { return _request; } set { if (value == null) { throw Error.PropertyNull(); } _request = value; } } public HttpRequestContext RequestContext { get { return _requestContext; } set { if (value == null) { throw Error.PropertyNull(); } _requestContext = value; } } public IHttpRouteData RouteData { get { return _requestContext.RouteData; } set { if (value == null) { throw Error.PropertyNull(); } _requestContext.RouteData = value; } } }
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() 獲取定在在控制器上的過濾器
public class HttpControllerDescriptor { //附加任何對象到該字典屬性 private readonly ConcurrentDictionary<object, object> _properties = new ConcurrentDictionary<object, object>(); private HttpConfiguration _configuration; private string _controllerName; private Type _controllerType; //緩存用 private object[] _attributeCache; private object[] _declaredOnlyAttributeCache; //后邊文章介紹,解析出ControllerType時候會調用該構造函數創建HttpControllerDescriptor public HttpControllerDescriptor(HttpConfiguration configuration, string controllerName, Type controllerType) { if (configuration == null) { throw Error.ArgumentNull("configuration"); } if (controllerName == null) { throw Error.ArgumentNull("controllerName"); } if (controllerType == null) { throw Error.ArgumentNull("controllerType"); } _configuration = configuration; _controllerName = controllerName; _controllerType = controllerType; //構造函數里直接調用Initialize Initialize(); } //默認構造函數,單元測試用 public HttpControllerDescriptor() { } //默認構造函數,單元測試用 internal HttpControllerDescriptor(HttpConfiguration configuration) { Initialize(configuration); } /// <summary> /// 附加任何對象到該字典屬性 /// </summary> public virtual ConcurrentDictionary<object, object> Properties { get { return _properties; } } public HttpConfiguration Configuration { get { return _configuration; } set { if (value == null) { throw Error.PropertyNull(); } _configuration = value; } } //控制器名稱 public string ControllerName { get { return _controllerName; } set { if (value == null) { throw Error.PropertyNull(); } _controllerName = value; } } //控制器類型 public Type ControllerType { get { return _controllerType; } set { if (value == null) { throw Error.PropertyNull(); } _controllerType = value; } } //主要方法 根據HttpRequestMessage創建一個IHttpController public virtual IHttpController CreateController(HttpRequestMessage request) { if (request == null) { throw Error.ArgumentNull("request"); } //先從ServicesContainer獲取默認的IHttpControllerActivator IHttpControllerActivator activator = Configuration.Services.GetHttpControllerActivator(); //調用IHttpControllerActivator的Create方法,創建,這個后一篇會說到 IHttpController instance = activator.Create(request, this, ControllerType); return instance; } //描述符對應的控制器定義的過濾器列表 public virtual Collection<IFilter> GetFilters() { return GetCustomAttributes<IFilter>(); } //獲取泛型的自定義特性的集合,對應控制器上定義的 public virtual Collection<T> GetCustomAttributes<T>() where T : class { return GetCustomAttributes<T>(inherit: true); } //獲取泛型的自定義特性的集合,對應控制器上定義的 public virtual Collection<T> GetCustomAttributes<T>(bool inherit) where T : class { object[] attributes; //反射獲取自定義特性很慢,所以使用緩存_attributeCache,第二次開始,就直接從其獲取 //inherit決定是否要去控制器類型繼承結構中去找所有特性 if (inherit) { if (_attributeCache == null) { _attributeCache = ControllerType.GetCustomAttributes(inherit: true); } attributes = _attributeCache; } else { if (_declaredOnlyAttributeCache == null) { //是從ControllerType屬性上去尋找特性的 _declaredOnlyAttributeCache = ControllerType.GetCustomAttributes(inherit: false); } attributes = _declaredOnlyAttributeCache; } return new Collection<T>(TypeHelper.OfType<T>(attributes)); } private void Initialize() { InvokeAttributesOnControllerType(this, ControllerType); } //先略過 private static void InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type) { Contract.Assert(controllerDescriptor != null); if (type == null) { return; } InvokeAttributesOnControllerType(controllerDescriptor, type.BaseType); object[] attrs = type.GetCustomAttributes(inherit: false); foreach (object attr in attrs) { var controllerConfig = attr as IControllerConfiguration; if (controllerConfig != null) { var originalConfig = controllerDescriptor.Configuration; var controllerSettings = new HttpControllerSettings(originalConfig); controllerConfig.Initialize(controllerSettings, controllerDescriptor); controllerDescriptor.Configuration = HttpConfiguration.ApplyControllerSettings(controllerSettings, originalConfig); } } } }
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異常。
public abstract class ApiController : IHttpController, IDisposable { private HttpActionContext _actionContext = new HttpActionContext(); private bool _initialized; //獲取HttpConfiguration //setter 單元測試用 public HttpConfiguration Configuration { get { return ControllerContext.Configuration; } set { ControllerContext.Configuration = value; } } //獲取HttpControllerContext //setter 單元測試用 public HttpControllerContext ControllerContext { get { // unit test only if (ActionContext.ControllerContext == null) { ActionContext.ControllerContext = new HttpControllerContext { RequestContext = new RequestBackedHttpRequestContext() }; } return ActionContext.ControllerContext; } set { if (value == null) { throw Error.PropertyNull(); } ActionContext.ControllerContext = value; } } //獲取HttpRequestMessage //setter 單元測試用 public HttpActionContext ActionContext { get { return _actionContext; } set { if (value == null) { throw Error.PropertyNull(); } _actionContext = value; } } //在模型綁定之后獲取ModelState,綁定之前是空的,模型綁定以后再說 public ModelStateDictionary ModelState { get { return ActionContext.ModelState; } } //獲取HttpRequestMessage //setter 單元測試用 public HttpRequestMessage Request { get { return ControllerContext.Request; } set { if (value == null) { throw Error.PropertyNull(); } HttpRequestContext contextOnRequest = value.GetRequestContext(); HttpRequestContext contextOnController = RequestContext; if (contextOnRequest != null && contextOnRequest != contextOnController) { // Prevent unit testers from setting conflicting requests contexts. throw new InvalidOperationException(SRResources.RequestContextConflict); } ControllerContext.Request = value; value.SetRequestContext(contextOnController); RequestBackedHttpRequestContext requestBackedContext = contextOnController as RequestBackedHttpRequestContext; if (requestBackedContext != null) { requestBackedContext.Request = value; } } } //獲取HttpRequestContext //setter 單元測試用 public HttpRequestContext RequestContext { get { return ControllerContext.RequestContext; } set { if (value == null) { throw Error.PropertyNull(); } HttpRequestContext oldContext = ControllerContext.RequestContext; HttpRequestMessage request = Request; if (request != null) { HttpRequestContext contextOnRequest = request.GetRequestContext(); if (contextOnRequest != null && contextOnRequest != oldContext && contextOnRequest != value) { // Prevent unit testers from setting conflicting requests contexts. throw new InvalidOperationException(SRResources.RequestContextConflict); } request.SetRequestContext(value); } ControllerContext.RequestContext = value; } } //獲取UrlHelper用來對其他APIS生成URLS //setter 單元測試用 public UrlHelper Url { get { return RequestContext.Url; } set { RequestContext.Url = value; } } //獲取或設置當前請求的Principal //setter 單元測試用 public IPrincipal User { get { return RequestContext.Principal; } set { RequestContext.Principal = value; } } //主要方法,創建控制器對象后,會調用ExecuteAsync方法,進行后續操作,由於還沒講控制器的創建,里邊的邏輯以后再細說 public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) { if (_initialized) { // 如果已經創建過該實例,就拋出異常,一個控制器實例,多次請求不能重復使用 throw Error.InvalidOperation(SRResources.CannotSupportSingletonInstance, typeof(ApiController).Name, typeof(IHttpControllerActivator).Name); } Initialize(controllerContext); if (Request != null) { //先注冊到待銷毀集合,待請求完成后一起銷毀改控制器實例 Request.RegisterForDispose(this); } HttpControllerDescriptor controllerDescriptor = controllerContext.ControllerDescriptor; ServicesContainer controllerServices = controllerDescriptor.Configuration.Services; //選擇Action HttpActionDescriptor actionDescriptor = controllerServices.GetActionSelector().SelectAction(controllerContext); ActionContext.ActionDescriptor = actionDescriptor; if (Request != null) { Request.SetActionDescriptor(actionDescriptor); } FilterGrouping filterGrouping = actionDescriptor.GetFilterGrouping(); //ActionFilters IActionFilter[] actionFilters = filterGrouping.ActionFilters; //身份認證過濾器 IAuthenticationFilter[] authenticationFilters = filterGrouping.AuthenticationFilters; //授權過濾器 IAuthorizationFilter[] authorizationFilters = filterGrouping.AuthorizationFilters; //ExceptionFilters IExceptionFilter[] exceptionFilters = filterGrouping.ExceptionFilters; IHttpActionResult result = new ActionFilterResult(actionDescriptor.ActionBinding, ActionContext, controllerServices, actionFilters); if (authorizationFilters.Length > 0) { result = new AuthorizationFilterResult(ActionContext, authorizationFilters, result); } if (authenticationFilters.Length > 0) { result = new AuthenticationFilterResult(ActionContext, this, authenticationFilters, result); } if (exceptionFilters.Length > 0) { IExceptionLogger exceptionLogger = ExceptionServices.GetLogger(controllerServices); IExceptionHandler exceptionHandler = ExceptionServices.GetHandler(controllerServices); result = new ExceptionFilterResult(ActionContext, exceptionFilters, exceptionLogger, exceptionHandler, result); } //執行IHttpActionResult的ExecuteAsync return result.ExecuteAsync(cancellationToken); } //驗證entity,並把驗證錯誤添加到ModelState public void Validate<TEntity>(TEntity entity) { Validate(entity, keyPrefix: String.Empty); } //驗證entity,並把驗證錯誤添加到ModelState public void Validate<TEntity>(TEntity entity, string keyPrefix) { if (Configuration == null) { throw Error.InvalidOperation(SRResources.TypePropertyMustNotBeNull, typeof(ApiController).Name, "Configuration"); } IBodyModelValidator validator = Configuration.Services.GetBodyModelValidator(); if (validator != null) { ModelMetadataProvider metadataProvider = Configuration.Services.GetModelMetadataProvider(); Contract.Assert(metadataProvider != null, "GetModelMetadataProvider throws on null."); validator.Validate(entity, typeof(TEntity), metadataProvider, ActionContext, keyPrefix); } } //創建一個400 Bad Request,項目中的Controller里可以直接使用 protected internal virtual BadRequestResult BadRequest() { return new BadRequestResult(this); } //根據message 創建一個400 Bad Request,項目中的Controller里可以直接使用 protected internal virtual BadRequestErrorMessageResult BadRequest(string message) { return new BadRequestErrorMessageResult(message, this); } //根據指定的modelState創建一個 400 Bad Request. protected internal virtual InvalidModelStateResult BadRequest(ModelStateDictionary modelState) { return new InvalidModelStateResult(modelState, this); } //創建一個 409 Conflict protected internal virtual ConflictResult Conflict() { return new ConflictResult(this); } /// <summary>創建一個內容協商結果響應</summary> /// <typeparam name="T">主體內容中的數據類型</typeparam> /// <param name="statusCode">響應狀態碼</param> /// <param name="value">在主體中要協商和格式化的數據</param> /// <returns>A <see cref="NegotiatedContentResult{T}"/> with the specified values.</returns> protected internal virtual NegotiatedContentResult<T> Content<T>(HttpStatusCode statusCode, T value) { return new NegotiatedContentResult<T>(statusCode, value, this); } /// <summary>創建一個指定格式化的內容響應</summary> /// <typeparam name="T">主體內容中的數據類型</typeparam> /// <param name="statusCode">響應狀態碼</param> /// <param name="value">在主體中要協商和格式化的數據</param> /// <param name="formatter">格式化器</param> /// <returns>A <see cref="FormattedContentResult{T}"/> with the specified values.</returns> protected internal FormattedContentResult<T> Content<T>(HttpStatusCode statusCode, T value, MediaTypeFormatter formatter) { return Content(statusCode, value, formatter, (MediaTypeHeaderValue)null); } /// <summary>創建一個指定媒體類型的格式化的內容響應</summary> /// <typeparam name="T">主體內容中的數據類型</typeparam> /// <param name="statusCode">響應狀態碼</param> /// <param name="value">在主體中要協商和格式化的數據</param> /// <param name="formatter">格式化器</param> /// <param name="mediaType">媒體類型</param> /// <returns>A <see cref="FormattedContentResult{T}"/> with the specified values.</returns> protected internal FormattedContentResult<T> Content<T>(HttpStatusCode statusCode, T value, MediaTypeFormatter formatter, string mediaType) { return Content(statusCode, value, formatter, new MediaTypeHeaderValue(mediaType)); } /// <summary>創建一個指定媒體類型的格式化的內容響應</summary> /// <typeparam name="T">主體內容中的數據類型</typeparam> /// <param name="statusCode">響應狀態碼</param> /// <param name="value">在主體中要協商和格式化的數據</param> /// <param name="formatter">格式化器</param> /// <param name="mediaType">媒體類型</param> /// <returns>A <see cref="FormattedContentResult{T}"/> with the specified values.</returns> protected internal virtual FormattedContentResult<T> Content<T>(HttpStatusCode statusCode, T value, MediaTypeFormatter formatter, MediaTypeHeaderValue mediaType) { return new FormattedContentResult<T>(statusCode, value, formatter, mediaType, this); } /// <summary> /// 創建一個201 Created 響應Created /// </summary> /// <typeparam name="T">The type of content in the entity body.</typeparam> /// <param name="location"> /// The location at which the content has been created. Must be a relative or absolute URL. /// </param> /// <param name="content">The content value to negotiate and format in the entity body.</param> /// <returns>A <see cref="CreatedNegotiatedContentResult{T}"/> with the specified values.</returns> protected internal CreatedNegotiatedContentResult<T> Created<T>(string location, T content) { if (location == null) { throw new ArgumentNullException("location"); } return Created<T>(new Uri(location, UriKind.RelativeOrAbsolute), content); } /// <summary> /// 創建一個201 Created 響應Created /// </summary> /// <typeparam name="T">The type of content in the entity body.</typeparam> /// <param name="location">The location at which the content has been created.</param> /// <param name="content">The content value to negotiate and format in the entity body.</param> /// <returns>A <see cref="CreatedNegotiatedContentResult{T}"/> with the specified values.</returns> protected internal virtual CreatedNegotiatedContentResult<T> Created<T>(Uri location, T content) { return new CreatedNegotiatedContentResult<T>(location, content, this); } /// <summary> /// 創建一個201 Created 響應Created /// </summary> /// <typeparam name="T">The type of content in the entity body.</typeparam> /// <param name="routeName">The name of the route to use for generating the URL.</param> /// <param name="routeValues">The route data to use for generating the URL.</param> /// <param name="content">The content value to negotiate and format in the entity body.</param> /// <returns>A <see cref="CreatedAtRouteNegotiatedContentResult{T}"/> with the specified values.</returns> protected internal CreatedAtRouteNegotiatedContentResult<T> CreatedAtRoute<T>(string routeName, object routeValues, T content) { return CreatedAtRoute<T>(routeName, new HttpRouteValueDictionary(routeValues), content); } /// <summary> /// 創建一個201 Created 響應Created /// </summary> /// <typeparam name="T">The type of content in the entity body.</typeparam> /// <param name="routeName">The name of the route to use for generating the URL.</param> /// <param name="routeValues">The route data to use for generating the URL.</param> /// <param name="content">The content value to negotiate and format in the entity body.</param> /// <returns>A <see cref="CreatedAtRouteNegotiatedContentResult{T}"/> with the specified values.</returns> protected internal virtual CreatedAtRouteNegotiatedContentResult<T> CreatedAtRoute<T>(string routeName, IDictionary<string, object> routeValues, T content) { return new CreatedAtRouteNegotiatedContentResult<T>(routeName, routeValues, content, this); } //創建一個 500 Internal Server Error protected internal virtual InternalServerErrorResult InternalServerError() { return new InternalServerErrorResult(this); } //根據異常創建一個 500 Internal Server Error protected internal virtual ExceptionResult InternalServerError(Exception exception) { return new ExceptionResult(exception, this); } /// <summary>創建一個 200 OK 響應,主體內容有JSON格式的數據,JsonSerializerSettings 序列化器</summary> /// <typeparam name="T">主體內容的數據類型</typeparam> /// <param name="content">序列化到主體部分的內容</param> /// <returns>A <see cref="JsonResult{T}"/> with the specified value.</returns> protected internal JsonResult<T> Json<T>(T content) { return Json<T>(content, new JsonSerializerSettings()); } /// <summary>創建一個 200 OK 響應,主體內容有JSON格式的數據, UTF8Encoding編碼</summary> /// <typeparam name="T">主體內容的數據類型</typeparam> /// <param name="content">序列化到主體部分的內容</param> /// <param name="serializerSettings">序列化器</param> /// <returns>A <see cref="JsonResult{T}"/> with the specified values.</returns> protected internal JsonResult<T> Json<T>(T content, JsonSerializerSettings serializerSettings) { return Json<T>(content, serializerSettings, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true)); } /// 創建一個 200 OK 響應,主體內容有JSON格式的數據 /// <typeparam name="T">主體內容的數據類型.</typeparam> /// <param name="content">序列化到主體部分的內容.</param> /// <param name="serializerSettings">序列化器</param> /// <param name="encoding">內容編碼</param> /// <returns>A <see cref="JsonResult{T}"/> with the specified values.</returns> protected internal virtual JsonResult<T> Json<T>(T content, JsonSerializerSettings serializerSettings, Encoding encoding) { return new JsonResult<T>(content, serializerSettings, encoding, this); } //創建一個 404 Not Found 響應 protected internal virtual NotFoundResult NotFound() { return new NotFoundResult(this); } //創建一個 200 OK 響應 protected internal virtual OkResult Ok() { return new OkResult(this); } //根據指定主體內容創建 OkNegotiatedContentResult(200 OK) protected internal virtual OkNegotiatedContentResult<T> Ok<T>(T content) { return new OkNegotiatedContentResult<T>(content, this); } //根據指定值創建一個Redirect 302 Found,參數用來生成URL protected internal virtual RedirectResult Redirect(string location) { if (location == null) { throw new ArgumentNullException("location"); } return Redirect(new Uri(location)); } //根據指定值創建一個RedirectResult 302 Found,參數用來生成URL protected internal virtual RedirectResult Redirect(Uri location) { return new RedirectResult(location, this); } //根據指定值創建一個RedirectToRouteResult 302 Found,參數用來生成URL protected internal RedirectToRouteResult RedirectToRoute(string routeName, object routeValues) { return RedirectToRoute(routeName, new HttpRouteValueDictionary(routeValues)); } //根據指定值創建一個RedirectToRouteResult 302 Found,參數用來生成URL protected internal virtual RedirectToRouteResult RedirectToRoute(string routeName, IDictionary<string, object> routeValues) { return new RedirectToRouteResult(routeName, routeValues, this); } //根據HttpResponseMessage創建一個ResponseMessageResult protected internal virtual ResponseMessageResult ResponseMessage(HttpResponseMessage response) { return new ResponseMessageResult(response); } /// 根據指定的HttpStatusCode創建StatusCodeResult protected internal virtual StatusCodeResult StatusCode(HttpStatusCode status) { return new StatusCodeResult(status, this); } // 根據指定值 創建401 未授權 響應 //challenges 為 The WWW-Authenticate challenges. protected internal UnauthorizedResult Unauthorized(params AuthenticationHeaderValue[] challenges) { return Unauthorized((IEnumerable<AuthenticationHeaderValue>)challenges); } // 根據指定值 創建401 未授權 響應 //challenges 為 The WWW-Authenticate challenges. protected internal virtual UnauthorizedResult Unauthorized(IEnumerable<AuthenticationHeaderValue> challenges) { return new UnauthorizedResult(challenges, this); } //標記_initialized = true說明已經被使用,不能重復使用,即同一個控制器實例只能被使用於一次請求 protected virtual void Initialize(HttpControllerContext controllerContext) { if (controllerContext == null) { throw Error.ArgumentNull("controllerContext"); } _initialized = true; ControllerContext = controllerContext; } #region IDisposable public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { } #endregion IDisposable }