在 ApiController 中添加自定义响应 header
Add a custom response header in ApiController
到目前为止,我有一个 GET
方法,如下所示:
protected override async Task<IHttpActionResult> GetAll(QueryData query)
{
// ... Some operations
//LINQ Expression based on the query parameters
Expression<Func<Entity, bool>> queryExpression = BuildQueryExpression(query);
//Begin to count all the entities in the repository
Task<int> countingEntities = repo.CountAsync(queryExpression);
//Reads an entity that will be the page start
Entity start = await repo.ReadAsync(query.Start);
//Reads all the entities starting from the start entity
IEnumerable<Entity> found = await repo.BrowseAllAsync(start, queryExpression);
//Truncates to page size
found = found.Take(query.Size);
//Number of entities returned in response
int count = found.Count();
//Number of total entities (without pagination)
int total = await countingEntities;
return Ok(new {
Total = total,
Count = count,
Last = count > 0 ? GetEntityKey(found.Last()) : default(Key),
Data = found.Select(e => IsResourceOwner(e) ? MapToOwnerDTO(e) : MapToDTO(e)).ToList()
});
}
这很有效,而且很好。但是,最近有人告诉我发送响应 metadata(即 Total
、Count
和 Last
属性)作为响应自定义 headers 而不是响应 body.
我无法从 ApiController 访问 Response
。我想到了过滤器或属性,但如何获取元数据值?
我可以将所有这些信息保留在响应中,然后有一个过滤器在发送到客户端之前反序列化响应,并使用 headers 创建一个新的,但这看起来很麻烦而且很糟糕.
是否可以通过此方法直接在 ApiController
上添加自定义 headers?
您可以使用自定义 ActionFilter,它允许您发送自定义 headers 并访问 HttpContext:
public class AddCustomHeaderFilter : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
actionExecutedContext.Response.Content.Headers.Add("name", "value");
}
}
我已输入评论,这是我的完整答案。
您需要创建一个自定义过滤器并将其应用于您的控制器。
public class CustomHeaderFilter : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var count = actionExecutedContext.Request.Properties["Count"];
actionExecutedContext.Response.Content.Headers.Add("totalHeader", count);
}
}
在你的控制器中
public class AddressController : ApiController
{
public async Task<Address> Get()
{
Request.Properties["Count"] = "123";
}
}
您可以在如下方法中显式添加自定义 headers:
[HttpGet]
[Route("home/students")]
public HttpResponseMessage GetStudents()
{
// Get students from Database
// Create the response
var response = Request.CreateResponse(HttpStatusCode.OK, students);
// Set headers for paging
response.Headers.Add("X-Students-Total-Count", students.Count());
return response;
}
有关详细信息,请阅读这篇文章:http://www.jerriepelser.com/blog/paging-in-aspnet-webapi-http-headers/
您需要的是:
public async Task<IHttpActionResult> Get()
{
var response = Request.CreateResponse();
response.Headers.Add("Lorem", "ipsum");
return base.ResponseMessage(response);
}
我希望这能回答您的问题。
简单的解决方案就是这样写:
HttpContext.Current.Response.Headers.Add("MaxRecords", "1000");
或者,如果您需要对每个响应执行某些操作,则最好利用 DelegatingHandler。因为它将在 request/response 管道上工作,而不是在 controller/action 级别上工作。在我的例子中,我必须在每个回复中添加一些 headers,所以我做了我描述的。请参阅下面的代码片段
public class Interceptor : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Methods", "GET,POST,PATCH,DELETE,PUT,OPTIONS");
response.Headers.Add("Access-Control-Allow-Headers", "Origin, Content-Type, X-Auth-Token, content-type");
return response;
}
}
并且您需要在 WebApiConfig 中添加此处理程序
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new Interceptor());
}
}
到目前为止,我有一个 GET
方法,如下所示:
protected override async Task<IHttpActionResult> GetAll(QueryData query)
{
// ... Some operations
//LINQ Expression based on the query parameters
Expression<Func<Entity, bool>> queryExpression = BuildQueryExpression(query);
//Begin to count all the entities in the repository
Task<int> countingEntities = repo.CountAsync(queryExpression);
//Reads an entity that will be the page start
Entity start = await repo.ReadAsync(query.Start);
//Reads all the entities starting from the start entity
IEnumerable<Entity> found = await repo.BrowseAllAsync(start, queryExpression);
//Truncates to page size
found = found.Take(query.Size);
//Number of entities returned in response
int count = found.Count();
//Number of total entities (without pagination)
int total = await countingEntities;
return Ok(new {
Total = total,
Count = count,
Last = count > 0 ? GetEntityKey(found.Last()) : default(Key),
Data = found.Select(e => IsResourceOwner(e) ? MapToOwnerDTO(e) : MapToDTO(e)).ToList()
});
}
这很有效,而且很好。但是,最近有人告诉我发送响应 metadata(即 Total
、Count
和 Last
属性)作为响应自定义 headers 而不是响应 body.
我无法从 ApiController 访问 Response
。我想到了过滤器或属性,但如何获取元数据值?
我可以将所有这些信息保留在响应中,然后有一个过滤器在发送到客户端之前反序列化响应,并使用 headers 创建一个新的,但这看起来很麻烦而且很糟糕.
是否可以通过此方法直接在 ApiController
上添加自定义 headers?
您可以使用自定义 ActionFilter,它允许您发送自定义 headers 并访问 HttpContext:
public class AddCustomHeaderFilter : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
actionExecutedContext.Response.Content.Headers.Add("name", "value");
}
}
我已输入评论,这是我的完整答案。
您需要创建一个自定义过滤器并将其应用于您的控制器。
public class CustomHeaderFilter : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var count = actionExecutedContext.Request.Properties["Count"];
actionExecutedContext.Response.Content.Headers.Add("totalHeader", count);
}
}
在你的控制器中
public class AddressController : ApiController
{
public async Task<Address> Get()
{
Request.Properties["Count"] = "123";
}
}
您可以在如下方法中显式添加自定义 headers:
[HttpGet]
[Route("home/students")]
public HttpResponseMessage GetStudents()
{
// Get students from Database
// Create the response
var response = Request.CreateResponse(HttpStatusCode.OK, students);
// Set headers for paging
response.Headers.Add("X-Students-Total-Count", students.Count());
return response;
}
有关详细信息,请阅读这篇文章:http://www.jerriepelser.com/blog/paging-in-aspnet-webapi-http-headers/
您需要的是:
public async Task<IHttpActionResult> Get()
{
var response = Request.CreateResponse();
response.Headers.Add("Lorem", "ipsum");
return base.ResponseMessage(response);
}
我希望这能回答您的问题。
简单的解决方案就是这样写:
HttpContext.Current.Response.Headers.Add("MaxRecords", "1000");
或者,如果您需要对每个响应执行某些操作,则最好利用 DelegatingHandler。因为它将在 request/response 管道上工作,而不是在 controller/action 级别上工作。在我的例子中,我必须在每个回复中添加一些 headers,所以我做了我描述的。请参阅下面的代码片段
public class Interceptor : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Methods", "GET,POST,PATCH,DELETE,PUT,OPTIONS");
response.Headers.Add("Access-Control-Allow-Headers", "Origin, Content-Type, X-Auth-Token, content-type");
return response;
}
}
并且您需要在 WebApiConfig 中添加此处理程序
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new Interceptor());
}
}