ASP.NET Core RC2 Web Api'den HTTP 500 nasıl döndürülür?


189

RC1'e dönersek, bunu yapardım:

[HttpPost]
public IActionResult Post([FromBody]string something)
{    
    try{
        // ...
    }
    catch(Exception e)
    {
         return new HttpStatusCodeResult((int)HttpStatusCode.InternalServerError);
    }
}

RC2'de artık HttpStatusCodeResult yok ve 500 tür IActionResult'u döndürmeme izin veren hiçbir şey yok.

Yaklaşım şimdi sorduğum şey için tamamen farklı mı? Artık Controllerkodda deneme yapmıyor muyuz ? Çerçevenin, API arayanına genel 500 istisnası atmasına izin veriyor muyuz? Geliştirme için istisna yığınını nasıl görebilirim?

Yanıtlar:


243

Gördüğüm kadarıyla ControllerBasesınıf içinde yardımcı yöntemler var . Sadece StatusCodeyöntemi kullanın :

[HttpPost]
public IActionResult Post([FromBody] string something)
{    
    //...
    try
    {
        DoSomething();
    }
    catch(Exception e)
    {
         LogException(e);
         return StatusCode(500);
    }
}

StatusCode(int statusCode, object value)İçeriği de müzakere eden aşırı yükü de kullanabilirsiniz .


7
bunu yaptığımızda, CORS başlıklarını kaybederiz, bu nedenle hatalar tarayıcı istemcilerinden gizlenir. V sinir bozucu.
bbsimonbb

2
@bbsimonbb Dahili hatalar istemcilerden gizlenmelidir. Geliştiriciler için günlüğe kaydedilmelidir.
Himalaya Garg

10
Geliştiriciler, hangi düzeydeki hata bilgilerinin döndürüleceğini seçme ayrıcalığına sahip olmalıdırlar.
bbsimonbb

179

Sen kullanabilirsiniz Microsoft.AspNetCore.Mvc.ControllerBase.StatusCodeve Microsoft.AspNetCore.Http.StatusCodessen kod gömmek belirli numaralara istemiyorsanız, yanıtınızı oluşturmak üzere.

return  StatusCode(StatusCodes.Status500InternalServerError);

GÜNCELLEME: Ağu 2019

Belki de orijinal soru ile doğrudan ilgili değil, aynı sonucu elde etmeye çalışırken mecliste bulunan Microsoft Azure Functionsyeni bir StatusCodeResultnesne inşa etmem gerektiğini buldum Microsoft.AspNetCore.Mvc.Core. Kodum şimdi şöyle görünüyor;

return new StatusCodeResult(StatusCodes.Status500InternalServerError);

11
Büyük olan, kodlanmış parçalardan / "sihirli numaralardan" kaçınır. Daha önce StatusCode ((int) HttpStatusCode.InternalServerError) kullandım ama sizinkini daha iyi seviyorum.
aleor

1
O zaman dikkate almadım bir şey, kodu daha okunabilir hale getirir, geri dönerek 500 numarasının ne hata ile ilgili olduğunu biliyorsunuz, tam orada kodda. Kendini belgeleme :-)
Edward Comeau

11
Dahili sunucu hatasını (500) yakında değiştiremiyorum.
rulolar

2
müthiş. bu da gerçekten havalı niteliklerimi temizliyor. ör .: [
ProducesResponseType

43

Yanıtınızda bir gövdeye ihtiyacınız varsa,

return StatusCode(StatusCodes.Status500InternalServerError, responseObject);

Bu, yanıt nesnesiyle birlikte 500 değerini döndürür ...


3
Belirli bir yanıt nesnesi türü oluşturmak istemiyorsanız: return StatusCode(StatusCodes.Status500InternalServerError, new { message = "error occurred" });Ve elbette, istediğiniz kadar açıklayıcı bir mesaj ve diğer öğeleri de ekleyebilirsiniz.
Mike Taverne

18

Şimdilik bunu (1.1) daha iyi ele almanın daha iyi bir yolu, bunu Startup.cs's Configure():

app.UseExceptionHandler("/Error");

Bu işlem için rotayı yürütür /Error. Bu, yazdığınız her eyleme try-catch blokları eklemekten kurtaracaktır.

Elbette, buna benzer bir ErrorController eklemeniz gerekir:

[Route("[controller]")]
public class ErrorController : Controller
{
    [Route("")]
    [AllowAnonymous]
    public IActionResult Get()
    {
        return StatusCode(StatusCodes.Status500InternalServerError);
    }
}

Daha fazla bilgi burada .


Gerçek istisna verilerini almak istiyorsanız, bunu ifadeden Get()hemen önce yukarıdakilere ekleyebilirsiniz return.

// Get the details of the exception that occurred
var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();

if (exceptionFeature != null)
{
    // Get which route the exception occurred at
    string routeWhereExceptionOccurred = exceptionFeature.Path;

    // Get the exception that occurred
    Exception exceptionThatOccurred = exceptionFeature.Error;

    // TODO: Do something with the exception
    // Log it with Serilog?
    // Send an e-mail, text, fax, or carrier pidgeon?  Maybe all of the above?
    // Whatever you do, be careful to catch any exceptions, otherwise you'll end up with a blank page and throwing a 500
}

Snippet'in üstü Scott Sauber blogundan alındı .


bu harika, ama atılan istisnayı nasıl kaydedebilirim?
redwards510

@ redwards510 Bunu nasıl yapacağınız aşağıda açıklanmıştır: scottsauber.com/2017/04/03/… Çok yaygın bir kullanım örneği olduğu için cevabımı güncelleyeceğim 😊
gldraphael

@gldraphael Şu anda Core 2.1 kullanıyoruz. Scott'ın blogu harika, ancak IExceptionHandlerPathFeature kullanmanın şu anda önerilen en iyi uygulamalar olup olmadığını merak ediyorum. Belki özel ara katman yazılımı oluşturmak daha iyidir?
Pavel

@Pavel ExceptionHandlerburada ara katman yazılımı kullanıyoruz . Tabii ki, kendiniz yuvarlayabilir veya uygun gördüğünüzde uzatabilirsiniz. İşte kaynakların bağlantısı . EDIT: için bu satıra bakın IExceptionHandlerPathFeature .
gldraphael

15
return StatusCode((int)HttpStatusCode.InternalServerError, e);

ASP.NET dışı bağlamlarda kullanılmalıdır (ASP.NET Core için diğer yanıtlara bakın).

HttpStatusCodebir numaralandırmadır System.Net.


12

Bunun gibi İç Sunucu Hatası'nı temsil eden özel bir ObjectResult sınıfı oluşturmaya ne dersiniz OkObjectResult? Kolayca InternalServerError oluşturmak ve sizin gibi geri böylece Kendi taban sınıftaki basit bir yöntem koyabilirsiniz Ok()ya BadRequest().

[Route("api/[controller]")]
[ApiController]
public class MyController : MyControllerBase
{
    [HttpGet]
    [Route("{key}")]
    public IActionResult Get(int key)
    {
        try
        {
            //do something that fails
        }
        catch (Exception e)
        {
            LogException(e);
            return InternalServerError();
        }
    }
}

public class MyControllerBase : ControllerBase
{
    public InternalServerErrorObjectResult InternalServerError()
    {
        return new InternalServerErrorObjectResult();
    }

    public InternalServerErrorObjectResult InternalServerError(object value)
    {
        return new InternalServerErrorObjectResult(value);
    }
}

public class InternalServerErrorObjectResult : ObjectResult
{
    public InternalServerErrorObjectResult(object value) : base(value)
    {
        StatusCode = StatusCodes.Status500InternalServerError;
    }

    public InternalServerErrorObjectResult() : this(null)
    {
        StatusCode = StatusCodes.Status500InternalServerError;
    }
}

6

MVC .Net Core'da bir JSON yanıtı döndürmek istediğinizde şunları da kullanabilirsiniz:

Response.StatusCode = (int)HttpStatusCode.InternalServerError;//Equals to HTTPResponse 500
return Json(new { responseText = "my error" });

Bu, hem JSON sonucunu hem de HTTPStatus değerini döndürür. Ben sonuçları jQuery.ajax () döndürmek için kullanın.


1
Kullanmak zorunda kaldı return new JsonResult ...ama başka türlü harika çalıştı.
Mike Taverne

5

Aspnetcore-3.1 için Problem()aşağıdaki gibi de kullanabilirsiniz ;

https://docs.microsoft.com/en-us/aspnet/core/web-api/handle-errors?view=aspnetcore-3.1

 [Route("/error-local-development")]
public IActionResult ErrorLocalDevelopment(
    [FromServices] IWebHostEnvironment webHostEnvironment)
{
    if (webHostEnvironment.EnvironmentName != "Development")
    {
        throw new InvalidOperationException(
            "This shouldn't be invoked in non-development environments.");
    }

    var context = HttpContext.Features.Get<IExceptionHandlerFeature>();

    return Problem(
        detail: context.Error.StackTrace,
        title: context.Error.Message);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.