IHtpActionResult를 사용할 때 사용자 지정 헤더를 설정하는 방법은?
ASP.NET Web API 2에서,IHttpActionResult
컨트롤러 코드를 단순화하는 데 많은 가치를 제공하며 사용을 중단하기를 꺼려하지만 문제가 생겼습니다.
발신 응답에 ETag를 설정해야 하는데 응답 헤더에 접근할 수 있는 속성을 찾을 수 없습니다.지금 제가 사용하고 있는.Ok<T>(T content)
헬퍼 메소드(helper method)ApiController
, 개체를 반환합니다.노출된 것이 없어 보여서 머리글을 수정할 수 있을 것 같습니다.
제가 뭔가를 놓치고 있는 건가요, 아니면 정말 재고를 사용하면서 할 수 있는 방법이 없는 건가요.IHttpActionResult
유형? 메시지 핸들러를 고려했지만, 작업에서 ETag를 전달하는 방법을 알아내야 합니다(ETag는 다른 작업에 대해 다르게 생성되므로 모든 작업에 대해 일반 핸들러를 만드는 것이 문제가 아닙니다).
원시 HttpResponse Message를 사용할 필요는 없지만 현재로서는 어려워 보입니다.
시나리오의 경우 사용자 정의를 생성해야 합니다.IHttpActionResult
. 다음은 제가 도출한 예입니다.OkNegotiatedContentResult<T>
운행중에Content-Negotiation
설정합니다.Ok
상태 코드.
public class CustomOkResult<T> : OkNegotiatedContentResult<T>
{
public CustomOkResult(T content, ApiController controller)
: base(content, controller) { }
public CustomOkResult(T content, IContentNegotiator contentNegotiator, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
: base(content, contentNegotiator, request, formatters) { }
public string ETagValue { get; set; }
public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = await base.ExecuteAsync(cancellationToken);
response.Headers.ETag = new EntityTagHeaderValue(this.ETagValue);
return response;
}
}
컨트롤러:
public class ValuesController : ApiController
{
public IHttpActionResult Get()
{
return new CustomOkResult<string>(content: "Hello World!", controller: this)
{
ETagValue = "You ETag value"
};
}
}
또한 다음에서 유도할 수 있습니다.NegotiatedContentResult<T>
, 이 경우 상태 코드를 직접 제공해야 합니다.도움이 되길 바랍니다.
와 의 소스 코드를 찾을 수 있으며, 상상할 수 있듯이 실제로는 간단합니다.
를 생성할 수 있습니다.HttpResponseMessage
, 필요에 따라 머리글 추가 후 만들기ResponseMessageResult
여기서:
HttpResponseMessage response =new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.Add("MyHeader", "MyHeaderValue");
return ResponseMessage(response);
여기에 ActionFilterAttribute가 없는 간단한 구현이 있으며 AlexACD의 응답과 유사합니다.제 솔루션은 IHtpActionResult 인터페이스를 구현하는 ResponseMessageResult를 사용합니다.
HttpResponseMessage responseMessage = new HttpResponseMessage(HttpStatusCode.OK);
responseMessage.Headers.Add("Headername", "Value");
ResponseMessageResult response = new ResponseMessageResult(responseMessage);
return response;
public static class HttpExtentions
{
public static IHttpActionResult AddHeader(this IHttpActionResult action,
string headerName, IEnumerable<string> headerValues)
{
return new HeaderActionResult(action, headerName, headerValues);
}
public static IHttpActionResult AddHeader(this IHttpActionResult action,
string headerName, string header)
{
return AddHeader(action, headerName, new[] {header});
}
private class HeaderActionResult : IHttpActionResult
{
private readonly IHttpActionResult action;
private readonly Tuple<string, IEnumerable<string>> header;
public HeaderActionResult(IHttpActionResult action, string headerName,
IEnumerable<string> headerValues)
{
this.action = action;
header = Tuple.Create(headerName, headerValues);
}
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = await action.ExecuteAsync(cancellationToken);
response.Headers.Add(header.Item1, header.Item2);
return response;
}
}
}
아주 오래된 질문입니다.그 당시에는 다른 답변이 의미가 있었을 것입니다만, 오늘날에는 변경하거나 확장하지 않고 이 줄을 추가할 수 있습니다.IHttpActionResult
. 응답에 헤더를 완벽하게 추가합니다.또한 아래와 같이 RFC 1123 표준으로 포맷해야 합니다.그렇지 않으면 마지막으로 수정된 내용이 머리글에 나타나더라도 클라이언트는 다음을 사용하여 읽을 수 없습니다.HttpClient
.
System.Web.HttpContext.Current.Response.Headers.
Add(Microsoft.Net.Http.Headers.HeaderNames.LastModified, DBdateModified.Value.ToString("r"));
이는 컨트롤러 기능 후 응답을 검사하는 ActionFilterAttribute를 사용하여 달성할 수 있습니다. 컨트롤러 기능이 종료되기 전에 컨트롤러 메서드에 속성을 설정하여 이 정보를 추가할 수 있습니다. 다음은 제가 구현한 내용은 다음과 같습니다.
public class EnableETag : ActionFilterAttribute
{
/// <summary>
/// NOTE: a real production situation, especially when it involves a web garden
/// or a web farm deployment, the tags must be retrieved from the database or some other place common to all servers.
/// </summary>
private static ConcurrentDictionary<string, EntityTagHeaderValue> etags = new ConcurrentDictionary<string, EntityTagHeaderValue>();
public override void OnActionExecuting(HttpActionContext context)
{
var request = context.Request;
if (request.Method == HttpMethod.Get)
{
var key = GetKey(request);
ICollection<EntityTagHeaderValue> etagsFromClient = request.Headers.IfNoneMatch;
if (etagsFromClient.Count > 0)
{
EntityTagHeaderValue etag = null;
if (etags.TryGetValue(key, out etag) && etagsFromClient.Any(t => t.Tag == etag.Tag))
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotModified);
SetCacheControl(context.Response);
}
}
}
}
public override void OnActionExecuted(HttpActionExecutedContext context)
{
var request = context.Request;
var key = GetKey(request);
EntityTagHeaderValue etag;
if (!etags.TryGetValue(key, out etag) || request.Method == HttpMethod.Put ||
request.Method == HttpMethod.Post)
{
etag = new EntityTagHeaderValue("\"" + Guid.NewGuid().ToString() + "\"");
etags.AddOrUpdate(key, etag, (k, val) => etag);
}
context.Response.Headers.ETag = etag;
SetCacheControl(context.Response);
}
private string GetKey(HttpRequestMessage request)
{
return request.RequestUri.ToString();
}
/// <summary>
/// Defines the time period to hold item in cache (currently 10 seconds)
/// </summary>
/// <param name="response"></param>
private void SetCacheControl(HttpResponseMessage response)
{
response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(10),
MustRevalidate = true,
Private = true
};
}
}
}
은 인 Web API 2 기타 할 수 2 입니다. 이는 헤더 설정이나 기타 속성을 쉽게 지원할 수 있습니다.HttpResponseMessage
에 규정된ExecuteAsync
--어떤 NegotiatedContentResult
구현:
public class FlexibleNegotiatedContentResult<T> : NegotiatedContentResult<T>
{
private readonly Action<HttpResponseMessage> _responseMessageDelegate;
public FlexibleNegotiatedContentResult(HttpStatusCode statusCode, T content, IContentNegotiator contentNegotiator, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
: base(statusCode, content, contentNegotiator, request, formatters)
{
}
public FlexibleNegotiatedContentResult(HttpStatusCode statusCode, T content, ApiController controller, Action<HttpResponseMessage> responseMessageDelegate = null)
: base(statusCode, content, controller)
{
_responseMessageDelegate = responseMessageDelegate;
}
public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage responseMessage = await base.ExecuteAsync(cancellationToken);
if (_responseMessageDelegate != null)
{
_responseMessageDelegate(responseMessage);
}
return responseMessage;
}
}
사용 예시:
new FlexibleNegotiatedContentResult<string>(HttpStatusCode.Created, "Entity created!", controller, response => response.Headers.Location = new Uri("https://myapp.com/api/entity/1"));
언급URL : https://stackoverflow.com/questions/21440307/how-to-set-custom-headers-when-using-ihttpactionresult
'programing' 카테고리의 다른 글
jQuery에 전역 값(반드시 전역 변수가 아님)을 저장하는 방법? (0) | 2023.10.20 |
---|---|
구축 시 Swift 컴파일러 분할 오류 (0) | 2023.10.15 |
엔티티가 있는 xml에서 MySQL ExtractValue() (0) | 2023.10.15 |
워드프레스 태그를 프로그래밍적으로 만들려면 어떻게 해야 합니까? (0) | 2023.10.15 |
PowerShell로 텍스트 파일의 빈 줄 제거 (0) | 2023.10.15 |