Jak zwrócić NotFound () IHttpActionResult z Komunikatem o błędzie lub wyjątkiem?
Zwracam NotFound IHttpActionResult
, gdy coś nie znajduje się w mojej akcji GET WebAPI. Wraz z tą odpowiedzią chcę wysłać wiadomość niestandardową i/lub wiadomość wyjątku (jeśli taka istnieje). Aktualna metoda ApiController
' s NotFound()
nie zapewnia przeciążenia, aby przekazać wiadomość.
IHttpActionResult
? 10 answers
Musisz napisać własny wynik akcji, jeśli chcesz dostosować kształt wiadomości odpowiedzi.
Chcieliśmy po wyjęciu z pudełka dostarczyć najczęstsze kształty wiadomości odpowiedzi dla takich rzeczy, jak proste puste 404, ale chcieliśmy również, aby te wyniki były tak proste, jak to możliwe; jedną z głównych zalet korzystania z wyników akcji jest to, że znacznie ułatwia to test jednostkowy. Im więcej właściwości dodamy do wyników akcji, tym więcej rzeczy należy wziąć pod uwagę w teście jednostkowym aby upewnić się, że metoda działania robi to, czego można się spodziewać.
Często chcę mieć możliwość dostarczania niestandardowych wiadomości, więc nie krępuj się zarejestrować błąd, abyśmy rozważyli wsparcie tej akcji w przyszłym wydaniu: https://aspnetwebstack.codeplex.com/workitem/list/advanced
Jedną z fajnych rzeczy w wynikach akcji jest to, że zawsze możesz napisać swój własny dość łatwo, jeśli chcesz zrobić coś nieco innego. Oto jak możesz to zrobić w Twoim przypadku (zakładając, że chcesz komunikat o błędzie w text / plain; jeśli chcesz JSON, zrobisz coś nieco innego z treścią):
public class NotFoundTextPlainActionResult : IHttpActionResult
{
public NotFoundTextPlainActionResult(string message, HttpRequestMessage request)
{
if (message == null)
{
throw new ArgumentNullException("message");
}
if (request == null)
{
throw new ArgumentNullException("request");
}
Message = message;
Request = request;
}
public string Message { get; private set; }
public HttpRequestMessage Request { get; private set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
public HttpResponseMessage Execute()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.NotFound);
response.Content = new StringContent(Message); // Put the message in the response body (text/plain content).
response.RequestMessage = Request;
return response;
}
}
public static class ApiControllerExtensions
{
public static NotFoundTextPlainActionResult NotFound(this ApiController controller, string message)
{
return new NotFoundTextPlainActionResult(message, controller.Request);
}
}
Następnie, w swojej metodzie działania, możesz po prostu zrobić coś takiego:
public class TestController : ApiController
{
public IHttpActionResult Get()
{
return this.NotFound("These are not the droids you're looking for.");
}
}
Jeśli użyłeś niestandardowej klasy bazowej kontrolera (zamiast bezpośrednio dziedziczyć z ApiController), możesz również wyeliminować "this."część (która jest niestety wymagana przy wywołaniu metody rozszerzenia):
public class CustomApiController : ApiController
{
protected NotFoundTextPlainActionResult NotFound(string message)
{
return new NotFoundTextPlainActionResult(message, Request);
}
}
public class TestController : CustomApiController
{
public IHttpActionResult Get()
{
return NotFound("These are not the droids you're looking for.");
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-22 18:29:17
Oto jedna linijka do zwrotu IHttpActionResult Niefound z prostą wiadomością:
return Content(HttpStatusCode.NotFound, "Foo does not exist.");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-19 16:14:20
Możesz użyć ResponseMessageResult
jeśli chcesz:
var myCustomMessage = "your custom message which would be sent as a content-negotiated response";
return ResponseMessage(
Request.CreateResponse(
HttpStatusCode.NotFound,
myCustomMessage
)
);
Tak, jeśli potrzebujesz znacznie krótszych wersji, to chyba musisz zaimplementować swój niestandardowy wynik działania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 16:57:08
Możesz użyć właściwości ReasonPhrase klasy HttpResponseMessage
catch (Exception exception)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)
{
ReasonPhrase = exception.Message
});
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-22 07:49:02
Możesz utworzyć niestandardowy wynik negocjowanej zawartości zgodnie z sugestią d3m3t3er. Jednak odziedziczyłbym po nim. Ponadto, jeśli potrzebujesz go tylko do zwracania NotFound, nie musisz inicjalizować statusu http z konstruktora.
public class NotFoundNegotiatedContentResult<T> : NegotiatedContentResult<T>
{
public NotFoundNegotiatedContentResult(T content, ApiController controller)
: base(HttpStatusCode.NotFound, content, controller)
{
}
public override Task<HttpResponseMessage> ExecuteAsync(
CancellationToken cancellationToken)
{
return base.ExecuteAsync(cancellationToken).ContinueWith(
task => task.Result, cancellationToken);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-16 12:44:13
Rozwiązałem to po prostu poprzez wyprowadzenie z OkNegotiatedContentResult
i nadpisanie kodu HTTP w wynikowej wiadomości odpowiedzi. Ta klasa pozwala na zwrócenie zawartości ciała za pomocą dowolnego kodu odpowiedzi HTTP.
public class CustomNegotiatedContentResult<T> : OkNegotiatedContentResult<T>
{
public HttpStatusCode HttpStatusCode;
public CustomNegotiatedContentResult(
HttpStatusCode httpStatusCode, T content, ApiController controller)
: base(content, controller)
{
HttpStatusCode = httpStatusCode;
}
public override Task<HttpResponseMessage> ExecuteAsync(
CancellationToken cancellationToken)
{
return base.ExecuteAsync(cancellationToken).ContinueWith(
task => {
// override OK HTTP status code with our own
task.Result.StatusCode = HttpStatusCode;
return task.Result;
},
cancellationToken);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-06 13:55:33
Potrzebowałem stworzyć IHttpActionResult
instancję w ciele IExceptionHandler
klasy, w celu ustawienia właściwości ExceptionHandlerContext.Result
. Jednak chciałem również ustawić niestandardowy ReasonPhrase
.
Odkryłem, że a {[5] } może zawijać a HttpResponseMessage
(co pozwala łatwo ustawić ReasonPhrase).
Na Przykład:
public class MyExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
var ex = context.Exception as IRecordNotFoundException;
if (ex != null)
{
context.Result = new ResponseMessageResult(new HttpResponseMessage(HttpStatusCode.NotFound) { ReasonPhrase = $"{ex.EntityName} not found" });
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-04 07:23:13
Jeśli dziedziczysz z Bazy NegotitatedContentResult<T>
, Jak wspomniano, i nie musisz przekształcać swojego content
(np. chcesz tylko zwrócić łańcuch znaków), to nie musisz nadpisywać metody ExecuteAsync
.
Wystarczy podać odpowiednią definicję typu i konstruktor, który powie bazie, który kod statusu HTTP ma zwrócić. Wszystko inne po prostu działa.
Oto przykłady dla NotFound
i InternalServerError
:
public class NotFoundNegotiatedContentResult : NegotiatedContentResult<string>
{
public NotFoundNegotiatedContentResult(string content, ApiController controller)
: base(HttpStatusCode.NotFound, content, controller) { }
}
public class InternalServerErrorNegotiatedContentResult : NegotiatedContentResult<string>
{
public InternalServerErrorNegotiatedContentResult(string content, ApiController controller)
: base(HttpStatusCode.InternalServerError, content, controller) { }
}
I wtedy można utworzyć odpowiednie metody rozszerzenia dla ApiController
(lub zrób to w klasie bazowej, jeśli taką posiadasz):
public static NotFoundNegotiatedContentResult NotFound(this ApiController controller, string message)
{
return new NotFoundNegotiatedContentResult(message, controller);
}
public static InternalServerErrorNegotiatedContentResult InternalServerError(this ApiController controller, string message)
{
return new InternalServerErrorNegotiatedContentResult(message, controller);
}
I wtedy działają tak samo jak wbudowane metody. Możesz wywołać istniejącą NotFound()
lub nową niestandardową NotFound(myErrorMessage)
.
I oczywiście, możesz pozbyć się" twardych " typów łańcuchów w niestandardowych definicjach typu i pozostawić je ogólne, jeśli chcesz, ale wtedy Może będziesz musiał się martwić o ExecuteAsync
rzeczy, w zależności od tego, co <T>
faktycznie jest.
Możesz spojrzeć nad kodem źródłowym dla NegotiatedContentResult<T>
, aby zobaczyć wszystko, co robi. Nie ma w tym zbyt wiele.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-24 19:32:59
Wiem, że PO zapytało z tekstem wiadomości, ale inną opcją zwrócenia 404 jest zwrócenie metody ihttpactionresult i użycie funkcji StatusCode
public async Task<IHttpActionResult> Get([FromUri]string id)
{
var item = await _service.GetItem(id);
if(item == null)
{
StatusCode(HttpStatusCode.NotFound);
}
return Ok(item);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-06 16:24:44
Tutaj brakuje odpowiedzi na mały problem z fabułą programisty. Klasa ApiController
wciąż ujawnia metodę NotFound()
, której mogą używać Programiści. Spowodowałoby to, że niektóre 404 odpowiedzi zawierają niekontrolowany wynik ciała.
Przedstawiam tutaj kilka części kodu " better apicontroller NotFound method ", które zapewnią mniej podatną na błędy metodę, która nie wymaga od programistów znajomości "lepszego sposobu wysyłania 404".
- Utwórz klasę dziedzicząc z
ApiController
calledApiController
- używam tej techniki, aby uniemożliwić programistom używanie oryginalnej klasy
-
override its
NotFound
method to let devs use the first available api - jeśli chcesz to zniechęcić, oznacz to jako
[Obsolete("Use overload instead")]
- dodaj dodatkowe
protected NotFoundResult NotFound(string message)
które chcesz zachęcić - problem: wynik nie wspiera reakcji z ciałem. rozwiązanie: dziedziczenie i używanie
NegotiatedContentResult
. zobacz w załączeniu better NotFoundResult Klasa .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-06 11:02:39