ASP.NET Web API 框架研究 Controller创建 HttpController介绍
对请求进行路由解析以及消息处理管道进行处理后,最后可以从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 > )
{
result = new AuthorizationFilterResult(ActionContext, authorizationFilters, result);
}
if (authenticationFilters.Length > )
{
result = new AuthenticationFilterResult(ActionContext, this, authenticationFilters, result);
}
if (exceptionFilters.Length > )
{
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
}
ASP.NET Web API 框架研究 Controller创建 HttpController介绍的更多相关文章
- ASP.NET Web API 框架研究 Controller创建 HttpController 类型解析 选择 创建
上一篇介绍了HttpController的一些细节,接下来说下HttpController 类型解析.选择和创建.生产HttpController实例的生产线如下图: 一.涉及的类及源码分析 涉及的类 ...
- ASP.NET Web API 框架研究 Controller创建过程与消息处理管道
现在我们从代码角度来看下,从消息处理管道末尾是怎么创建出Controller实例的.消息处理管道末端是一个叫HttpRoutingDispatcher的处理器,其内部完成路由后 ,会把消息派送给其内部 ...
- ASP.NET Web API 框架研究 Controller实例的销毁
我们知道项目中创建的Controller,如ProductController都继承自ApiController抽象类,其又实现了接口IDisposable,所以,框架中自动调用Dispose方法来释 ...
- ASP.NET Web API 框架研究 ASP.NET Web API 路由
ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...
- ASP.NET Web API 框架研究 Action方法介绍
在根据请求解析出匹配的Controller类型并创建实例后,要在该Controller类型中的众多Action方法中选择与请求匹配的那一个,并执行,然后返回响应. Action方法,其元数据,主要包括 ...
- ASP.NET Web API 框架研究 核心的消息处理管道
ASP.NET Web API 的核心框架是一个由一组HttpMessageHandler有序组成的双工消息处理管道:寄宿监听到请求接受后,把消息传入该管道经过所有HttpMessageHandler ...
- ASP.NET Web API 框架研究 IoC容器 DependencyResolver
一.概念 1.IoC(Inversion of Control),控制反转 即将依赖对象的创建和维护交给一个外部容器来负责,而不是应用本身.如,在类型A中需要使用类型B的实例,而B的实例的创建不是由A ...
- ASP.NET Web API 框架研究 服务容器 ServicesContainer
ServicesContainer是一个服务的容器,可以理解为—个轻量级的IoC容器,其维护着一个服务接口类型与服务实例之间的映射关系,可以根据服务接口类型获取对应的服务实例.构成ASP.NET We ...
- ASP.NET Web API 框架研究 Self Host模式下的消息处理管道
Self Host模式下的ASP.NET Web API与WCF非常相似,都可以寄宿在任意类型的托管应用程序中,宿主可以是Windows Form .WPF.控制台应用以及Windows Servic ...
随机推荐
- 富文本编辑器--FCKEditor 上传图片
FCKEditor的最新版本已经更改名称为CKEditor: 1.在页面引入fckeditor目录下的fckeditor.js <script type="text/javascrip ...
- C单链表操作
#include <stdio.h> #include <stdlib.h> #define ElemType int #define Status int #define O ...
- 常用jvm参数
如果你是Eclipse ,可以通过 run -> Run Configurations->Arguments 添加-XX:+PrintGCDetails 打开gc日志 -Xmx 设置jav ...
- 常见CSS
.login_top_bg { background-image: url(/pcssc/images/login/login-top-bg.gif); background-repeat: repe ...
- MVVM Light 笔记 - snippet
RelayCommand有8个,看似很多,其实就是几个变化的组合: 1.是否Generic 2. 执行是使用lambda表达式还是method 3.是否有CanExecute 这些都在源代码Snipp ...
- android开发笔记(1)
最近老师要求我们使用android开发一些东西.但是对我们而言,android是一个未知的方面.先说说我对于android的软件的基本认识,首先他很难,因为他是一个未知的领域:其次,我们只是掌握了一些 ...
- 将excel的数据导入到数据库后都乱码了是怎么回事
将excel内容首先保存成csv格式,然后在MySQL数据库中导入,结果汉字出现了乱码. 解决过程: 1.csv文件以txt形式打开,另存为,选择utf-8编码. 2.数据库,设置,collation ...
- 2018.11.05 NOIP模拟 相交(dfs序+bit)
传送门 又TMTMTM考原题真是服. 考虑到两条路径相交一定满足某一条的lcalcalca在另外一条路径上面. 于是分开统计有多少个lcalcalca在当前路径上面以及有多少个路径经过了当前的lcal ...
- 吓死baobao了
早上远程连接服务器连不上,后面重启服务器,显示进入紧急修复模式:welcome to emergency mode!after logging in ,type “journalctl -xb” to ...
- IntelliJ IDEA 2017版 编译器使用学习笔记(七) (图文详尽版);IDE快捷键使用;IDE代码重构(编写高质量代码)
一.重构 重构变量:将语义模糊的变量名称改为更易理解的名称 修改变量名称,快键键 shift + F6 (输入要改的名字,所有位置相同的名字都会改变) 重构方法 ...