Web Api on Azure shows no error detail using 'return InternalServerError(ex)' - azure

My Web Api when run locally (in Release mode) will return any errors in this format:
{
"Message": "An error has occurred.",
"ExceptionMessage": "No text specified",
"ExceptionType": "System.Exception",
"StackTrace": null
}
But after deployment/publish to an Azure VM, only this remains:
{
"Message": "An error has occurred."
}
API code:
try
{
var msg = ...
new MessageService().SaveMessage(msg)); // <-- does some checks; may throw.
return Ok();
}
catch (Exception ex)
{
return InternalServerError(ex);
}
I'd like it to be more detailed on Azure, like the local result.
Can this be achieved, and if so, how?
I already (temporarily) removed <compilation xdt:Transform="RemoveAttributes(debug)" /> from the <system.web> part of Web.Release.config, and then re-deployed, but that made no difference.
Or am I using the wrong approach/pattern?
Obviously technical details should be limited, but right now we get no details at all.

You could try adding the following to your Global.asax:
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
Note: I wouldn't recommend that you keep this setting on in a production environment.

If instead you use
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Default;
then you can use the system.webServer error switch e.g.
<system.webServer>
<httpErrors errorMode="Detailed" existingResponse="PassThrough">
</httpErrors>
</system.webServer>
Note the existingResponse attribute to preserve the error message.

I had the same problem, the post is three years old, things have changed a little. If you setup a new Azure Mobile App with Visual Studio 2017 there is no longer a Global.asax.cs. I searched for hours, where to put this IncludeErrorDetailPolicy. It won't work without that setting.
You do it in your Startup.MobileApp.cs:
public partial class Startup
{
public static void ConfigureMobileApp(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
new MobileAppConfiguration()
.UseDefaultConfiguration()
.ApplyTo(config);
Don't forget, in your Web.config you also need to set:
<system.webServer>
<httpErrors errorMode="Detailed" existingResponse="PassThrough">
</httpErrors>
</system.webServer>
Don't use that for production environment!

For Web API 2, you can implement a custom IExceptionLogger that utilizes Azure Application Insights. Something like this:
using Microsoft.ApplicationInsights;
using System.Web.Http.ExceptionHandling;
namespace Your.Namespace.Here
{
public class TelemetryExceptionLogger : ExceptionLogger
{
private readonly TelemetryClient telemetryClient;
public TelemetryExceptionLogger(TelemetryClient telemetryClient)
{
this.telemetryClient = telemetryClient;
}
public override void Log(ExceptionLoggerContext context)
{
if (context != null && context.Exception != null)
{
telemetryClient.TrackException(context.Exception);
}
base.Log(context);
}
}
}
Then you need to register it with Web API:
using Microsoft.ApplicationInsights;
using System.Web.Http;
using System.Web.Http.ExceptionHandling;
using Your.Namespace.Here;
namespace Some.Other.Namespace.Or.The.Same
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// --- Normal Web API configuration here ---
config.Services.Add(typeof(IExceptionLogger), new TelemetryExceptionLogger(new TelemetryClient()));
}
}
}
For this to work, you will need to have set up Application Insight in Azure and for your VS project, but that is a story for another time :)
For more information, see Application Insights: Exception Telemetry

I have a scenario with the same error, and the problem was a copy&paste in the route header attribute of a method. I have the same route for two methods
[Route("test/Method1")]
public IHttpActionResult Method1(){...}
[Route("test/Method1")]
public IHttpActionResult Method2(){...}
Check the new methods and Routes added.

Related

How to customize default error pages in azure web app for linux?

I have hosted .NET core 3.1.1 LTS app in Azure web app for linux? How do I customize default error pages like
1. 502
2 Error pages when app service is stopped.
3 Error page when app is being published from Visual studio , VS code / FTP
I find a docs about creating Application Gateway custom error pages,maybe it's good for you. custom error pages
How to create custom error page in code.
We also can handle it by code.Here is my suggest.
Errors like 500, we can handle it by filter,
public class ErrorPageFilter : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext context)
{
if (context.HttpContext.Response.StatusCode == 500)
{
context.HttpContext.Response.Redirect("error/500");
}
base.OnResultExecuted(context);
}
}
[ErrorPageFilter]
public abstract class PageController
{}
For .netcore mvc project, it also comes with pipeline processing for error pages when it is created.
In startup.cs,
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//dev env show error page
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
//prod env show custom page
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
}
//In HomeController has this function,
//You just replace cshtml file by you want
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
Errors like 404, we can,
In startup.cs file find configure function,then add below code,
app.UseStatusCodePagesWithReExecute("/error/{0}");
Then add error Controller,
public class ErrorController : Controller
{
/// <summary>
/// In content in {0} is error code
/// </summary>
/// <returns></returns>
[Route("/error/{0}")]
public IActionResult Page()
{
//Jump to 404 error page
if (Response.StatusCode == 404)
{
return View("/views/error/notfound.cshtml");
}
return View();
}
}
Pay attention, if use ErroeController( handle 404 error), pls don't use
app.UseExceptionHandler("/Home/Error"),
you just need handle error in Controller.

Redirect ends up outside of application

I am working on a .Net Core web application and we would like to be able to redirect a type of url to our custom error page. The site is hosted on Azure and it seems that this error is not being handled in the application. Here is the type of URL I am working with:
www.mywebsite.com/%22http://www.yahoo.com/%22
The error page that is presented is the following:
The page cannot be displayed because an internal server error has occurred.
In addition when I check the live HTTP traffic on Azure it does not show an error occurring.
Edit:
Apparently azure cannot handle this type request at all: https://azure.microsoft.com/%22/http://www.google.com/
It looks for the config file within the second url. Does anyone know where I can file a bug with Microsoft?
I haven't tested this on Azure, however it works on our server.
Configure exceptions handling in Startup class.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// ...
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
}
// ...
app.UseStatusCodePagesWithRedirects("/error/{0}");
// ...
}
And error controller.
[Route("[controller]")]
public class ErrorController : Controller
{
[Route("")]
public IActionResult Index()
{
return View();
}
[Route("{httpStatusCode}")]
public IActionResult Index(int httpStatusCode)
{
// handle by error code
switch (httpStatusCode)
{
case (int)HttpStatusCode.NotFound:
return View("NotFound");
default:
return View();
}
}
}

Impossible to show Custom Error page with Nancy on OWIN

I have a website using Nancy which is hosted using OWIN.
In my Startup.cs file I define the PassThroughOptions as follows:
public void Configuration(IAppBuilder app)
{
app.UseNancy(o => {
o.PassThroughWhenStatusCodesAre(
HttpStatusCode.NotFound,
HttpStatusCode.InternalServerError
);
o.Bootstrapper = new Bootstrapper();
});
app.UseStageMarker(PipelineStage.MapHandler);
}
I need to pass-through the NotFound requests, so that things like my bundled .less files or miniprofiler-results or static files in the root of my site (robots.txt or sitemap.xml) work.
I also have a custom StatusCodeHandler for the 404 code, which also checks a custom header to distinguish between static files (or .less bundles/miniprofiler) and actual stuff that is not found in my modules' methods.
public void Handle(HttpStatusCode statusCode, NancyContext context)
{
Log.Warn("Not found: " + context.Request.Url);
base.Handle(statusCode, context, "Errors/NotFound");
}
This handler then should actually show the error page.
protected void Handle(HttpStatusCode statusCode, NancyContext context, string view)
{
var response = new Negotiator(context)
.WithModel(GetErrorModel(context))
.WithStatusCode(statusCode)
.WithView(view);
context.Response = responseNegotiator.NegotiateResponse(response, context);
}
But the error page is never shown. The request is processed three times and eventually the default IIS error page is shown (using errorMode="Custom" for httpErrors) or simply a white page (using existingResponse="PassThrough" for httpErrors).
Is there any way to display something so simple as a custom error page when hosting a Nancy website on OWIN?
What you've got there looks good, it looks like you've be using the Hosting Nancy with Owin docs.
Here's what works for me:
The Startup.cs (required for Owin): (We've both coded the configuration function differently, you're just using the extension helper while I'm not. Same result. This is in my App.Web project.)
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseNancy(options =>
{
options.Bootstrapper = new BootStrapper();
options.PerformPassThrough = context => context.Response.StatusCode == HttpStatusCode.NotFound;
});
app.UseStageMarker(PipelineStage.MapHandler);
}
}
404 handler: (As per the docs, doesn't matter where this is in the project, by implementing IStatusCodeHandler it'll be automatically picked up by Nancy This is in my App.WebApi project with other module classes.)
public class StatusCode404Handler : IStatusCodeHandler
{
public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context)
{
return statusCode == HttpStatusCode.NotFound;
}
public void Handle(HttpStatusCode statusCode, NancyContext context)
{
var response = new GenericFileResponse("statuspages/404.html", "text/html")
{
StatusCode = statusCode
};
context.Response = response;
}
}
The 'statuspages' folder in my App.Web project:
Check this SO post for a comparison of using GenericFileReponse or ViewRenderer (How to display my 404 page in Nancy?).

Custom Error Pages with ASP.NET MVC 5 and Elmah

I am trying make work custom error page in asp mvc 5 but for some strange reason at moment to test my page, from elmah i am loging two errors ( the real error what i am testing and a error related with error page not found:
The view 'Error' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/HotTowel/Error.aspx
~/Views/HotTowel/Error.ascx
~/Views/Shared/Error.aspx
~/Views/Shared/Error.ascx
~/Views/HotTowel/Error.cshtml
~/Views/HotTowel/Error.vbhtml
~/Views/Shared/Error.cshtml
~/Views/Shared/Error.vbhtml
I was looking into this url http://doingthedishes.com/2011/09/10/custom-errors-mvc-3-elmah.html, where the author had the same issue but with asp.net mvc 3. After read it, I tried remove the call to HandleErrorAttribute:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//filters.Add(new HandleErrorAttribute());
}
}
But the issue is still there: i can see my custom page but asp.net mvc is throwing two exceptions.
Any help?
the solution is rewrite a class derived from HandleErrorAttribute ?
like this post: keep getting The view "Error" not found when using Elmah and asp.net mvc 4 ?
You can do the following from ELMAH.MVC 2.0.2 is out:
Set disableHandleErrorFilter to true:
<add key="elmah.mvc.disableHandleErrorFilter" value="true" />
Remove filters.Add(new HandleErrorAttribute()); from FilterConfig class:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// filters.Add(new HandleErrorAttribute()); // <-- comment out
}
}
Here's a possible solution for you. I typically override the OnException method in a base controller class. filterContext.HttpContext.IsCustomErrorEnabled checks <customErrors> in the web.config. The showVerboseErrors variable is derived from a setting in the web.config.
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext.HttpContext.IsCustomErrorEnabled)
{
//trigger elmah
Elmah.ErrorSignal.FromCurrentContext().Raise(filterContext.Exception);
//get the last elmah error
var errorList = new List<ErrorLogEntry>();
Elmah.ErrorLog.GetDefault(filterContext.HttpContext.ApplicationInstance.Context).GetErrors(0, 1, errorList);
var error = errorList.LastOrDefault();
//return the custom error page
filterContext.Result = new ViewResult
{
ViewName = "~/Views/Shared/Error.cshtml",
ViewData = new ViewDataDictionary() {
{ "ErrorDetails", showVerboseErrors && error != null ? filterContext.Exception.Message : null },
{ "ErrorId", error != null ? error.Id : null }
}
};
//stop further error processing
filterContext.ExceptionHandled = true;
}
else
{
base.OnException(filterContext);
}
}

How do we integrate elmah logging in servicestack

I am new to servicestack and elman logging.
Can any body suggest how do we integrate elmah in service stack applications.
Thank you...
If you have an existing logging solution then you can use the ServiceStack.Logging.Elmah project. It is available via NuGet.
Exceptions, errors and fatal calls will be logged to Elmah in addition to the originally intended logger. For all other log types, only the original logger is used.
So if you are already using Log4Net then you can just configure Elmah like this
ElmahLogFactory factory = new ElmahLogFactory(new Log4NetFactory());
If you don't want to wrap in over an existing log then you can just research adding Elmah to any ASP.NET website. There is no reason it wouldn't work just because you are using ServiceStack.
using ServiceStack.Logging;
using ServiceStack.Logging.Elmah;
using ServiceStack.Logging.NLogger;
public AppHost()
: base(
"description",
typeof(MyService).Assembly)
{
LogManager.LogFactory = new ElmahLogFactory(new NLogFactory());
}
public override void Configure(Container container)
{
this.ServiceExceptionHandler += (request, exception) =>
{
// log your exceptions here
HttpContext context = HttpContext.Current;
ErrorLog.GetDefault(context).Log(new Error(exception, context));
// call default exception handler or prepare your own custom response
return DtoUtils.HandleException(this, request, exception);
};
// rest of your config
}
}
Now your ServiceStack error's appear in Elmah (assuming you've setup web.config etc).
Actually kampsj answer is better than Gavin's as Gavins causes double-logging to elmah by calling explicit elmah logger and then the default servicestack error handling...which itself already does the logging.
So really all you need is this (below assuming you want to wrap NLog with Elmah)
public class YourAppHost : AppHostBase
{
public YourAppHost() //Tell ServiceStack the name and where to find your web services
: base("YourAppName", typeof(YourService).Assembly)
{
LogManager.LogFactory = new ElmahLogFactory(new NLogFactory());
}
//...just normal stuff...
}
You could just have this above:
ElmahLogFactory factory = new ElmahLogFactory();
...but you probably should wrap another type of logger for non-error logging, like Debug and Warn.
This section on configuring Elmah and the Logging.Elmah UseCase for a working example of ServiceStack and Elmah configured together.
The ElmahLogFactory can be configured in your Global.asax before initializing the ServiceStack AppHost, e.g:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
var debugMessagesLog = new ConsoleLogFactory();
LogManager.LogFactory = new ElmahLogFactory(debugMessagesLog, this);
new AppHost().Init();
}
}

Resources