How to modify subject of Elmah emailing when using WebApi - asp.net-web-api

Normally in my Mvc project, I simply have a ErrorMail_Mailing method in Global.asax.cs which gives access to ErrorMailEventArgs.
But in WebApi, this method does not fire, so how can I access this information in Webapi?
I am currently using this methodology (which is working fine)
public class ApiErrorHandler : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
DepResolver.ExceptionHelper().LogToElmah(context.Exception);
base.OnException(context);
}
}

ELMAH doesn't fire on Web API by default. You need to either catch the error yourself and log it to ELMAH or even better, use the Elmah.Contrib.WebApi NuGet package: http://www.nuget.org/packages/Elmah.Contrib.WebApi/. With that package installed, simply add the following code to your Application_Start:
GlobalConfiguration.Configuration.Filters.Add(new ElmahHandleErrorApiAttribute());
This should trigger that your ErrorMail_Mailing method is called.

Related

Http Verb Attribute Not Working

I have decorated my service interface with Http Verb Attributes, but is not working.
Every method is treated as Post verb.
I'm using AspNetCore 1.1 and Abp packages 2.3.0
public interface ISettlementAppService : IApplicationService
{
Task<PagedResultDto<SettlementListDto>> GetPaged(GetSettlementInput input);
[HttpDelete]
Task Cancel(EntityDto<string> input);
}
For AspNet Core, add these attributes to the application service class, not to interface. Because they are handled by AspNet Core MVC (not by ABP) and it does not know about interfaces.
From the documentation (https://aspnetboilerplate.com/Pages/Documents/AspNet-Core#controllers):
Note: Previously, dynamic web api system was requiring to create service interfaces for application services. But this is not required for ASP.NET Core integration. Also, MVC attributes should be added to the service classes, even you have interfaces.
Do it like this;
public class SettlementAppService : ISettlementAppService
{
[HttpDelete]
Task Cancel(EntityDto<string> input){
//...
}
}

Global Error Handling in Service Fabric Stateless Web API

How should I handle global exception handling for my controller methods in stateless web API? My goal is to avoid verbosity of try/catch statements inside my controller.
I was able to achieve this with IIS hosted Web API using a custom ExceptionHandler which I register in my WebAPIConfig.cs. This won't work right-off-the-bat in OWIN hosted API (like in Service Fabric). So in SF stateless web API, I created an Owin middleware and registered that middleware in Startup.cs but it does not work. The catch block is ignored in the response pipeline in my middleware code.
...
public override async Task Invoke(IOwinContext context)
{
try
{
//It goes here
await Next.Invoke(context);
}
catch (Exception ex)
{
//This catch block does not get called????
HandleException(ex, context);
}
}
After a lot of digging for solutions, since there has been quite a lot of similar questons out there, I gained a better understanding about the Web API and OWIN pipeline. This question here in SO provided me a lot of info:Disable *all* exception handling in ASP.NET Web API 2 (to make room for my own)?
First-off, Web API exceptions are handled by default and that means the exception is handled so it does not propagate up the stacktrace. And that's the reason why, the catch block above (from my posted question) does not get called. In order for it to get called, I need to replace the IException handler of the Web API(in startup.cs) via this:
config.Services.Replace(typeof(IExceptionHandler), new PassthroughExceptionHandler());
All this custom handler does is forward the exception down the stack and let the OWIN global exception middleware do the work.
The PassthroughExceptionHandler is implemented like this:
public class PassthroughExceptionHandler : IExceptionHandler
{
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
var info = ExceptionDispatchInfo.Capture(context.Exception);
info.Throw();
}
}
Note that this uses ExceptionDispatchInfo . There are other solutions that have a different implementation but so far this one provided me what I need which is to ulimately wrap the exception into my common error response model in my OwinGlobalExceptionHandler.

how to use Elmah.Contrib.WebApi 1.0.9?

I am working on WEB API project. I want to implement global error handling and i choose ELMAH for that.
On googling i found i can implement ELMAH in WEB API with Elmah.Contrib.WebApi package.
So i installed the package Elmah.Contrib.WebApi and as written in author's github site i registered it.
so my global.asax looks like following.
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.Filters.Add(new ElmahHandleErrorApiAttribute());
GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageLoggingHandler());
}
but it does not seem to work. i also tried to find documentation on how to implement this package in project but could not find it.
can someone help me so i can get work that pacakge?
If you are using Web API 2, you should use the new exception logger:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
config.Services.Add(typeof(IExceptionLogger), new ElmahExceptionLogger());
...
}
}
Also shown in this post:
http://blog.elmah.io/logging-to-elmah-io-from-web-api/
(without the elmah.io package if you are using another log store)

Http.EnumRouteContraint must implement System.Web.Routing.IRouteConstraint

I'm using AttributeRouting in my Web API project. I've installed the AttributeRouting for Web API. I want to define an Enum route constraint so I setup my AttributeRoutingHttpConfig config as follows:
using System.Reflection;
using System.Web.Http;
using AttributeRouting.Web.Http.Constraints;
using AttributeRouting.Web.Http.WebHost;
using MyProject.Data.Models;
[assembly: WebActivator.PreApplicationStartMethod(typeof(PhantasyTour.AttributeRoutingHttpConfig), "Start")]
namespace MyProject
{
public static class AttributeRoutingHttpConfig
{
public static void RegisterRoutes(HttpRouteCollection routes)
{
routes.MapHttpAttributeRoutes(
config =>
{
config.AddRoutesFromAssembly(Assembly.GetExecutingAssembly());
config.InlineRouteConstraints.Add("ListType", typeof(EnumRouteConstraint<ListType>));
});
}
public static void Start()
{
RegisterRoutes(GlobalConfiguration.Configuration.Routes);
}
}
}
When I fire up my application I immediately receive the following error:
The constraint "AttributeRouting.Web.Http.Constraints.EnumRouteConstraint`1[[MyProject.Data.Models.ListType, MyProject.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" must implement System.Web.Routing.IRouteConstraint
I've looked at the source code for the AttributeRouting.Web.Http.Constraints.EnumRouteConstraint and confirmed that it implements IHttpRouteConstraint which presumably is the WebAPI equivalent of IRouteConstraint in the MVC namespace.
Does anyone know what I'm doing wrong and how I can get this working?
UPDATE:
I attempted to create a completely blank Web Application and add only WebAPI and AttributeRouting for WebAPI references. Despite having absolutely no references to MVC assemblies, I still receive the same error message. I did discover however that there is another EnumRouteConstraint found in the AttributeRouting.Web.Constraints namespace which works perfectly. It doesn't appear to be MVC specific since it is located in the Core AttributeRouting assembly. I would love to know why there are two different EnumRouteConstraint classes when only one of them works. But that is a question for another time.
It is interesting that the exception you get refers to the MVC interface from the namespace System.Web.Routing.
I would take it as a clue and look at all the references in your project, any place in the config where MVC Routes and Http Routes could have been mixed up.
If possible and if you have any at all, try removing all references to MVC (or System.Web.Routing for a start), and MVC flavour of attribute routing (if it's a separate dll).

WebAPI: Accessing Child Container as a Service Locator

In normal ASP.MVC projects we configure the dependency resolver with Unity and the Unity.Mvc3 package from http://unitymvc3.codeplex.com/
We have this test service registered with a HierarchicalLifetimeManager
container.RegisterType<ITestService, TestService>(new HierarchicalLifetimeManager());
And we hook up the container with Mvc in Global.asax.cs:
System.Web.Mvc.DependencyResolver.SetResolver(new Unity.Mvc3.UnityDependencyResolver(container));
And we run this test controller:
public class TestController : Controller
{
private readonly ITestService _service;
public TestController(ITestService service)
{
this._service = service;
}
public ActionResult Test()
{
var locatedService = System.Web.Mvc.DependencyResolver.Current.GetService<ITestService>();
if (_service == locatedService)
return View("Success - Same Service");//This is always the result in an MVC controller
else
throw new Exception("Failure - Different Service Located");//This is never the result in an MVC controller
}
}
However, on this project we are adding a number of WebAPI controllers.
We have this configuration in global.asax.cs (using http://unitywebapi.codeplex.com/ for now. But I am open to suggestions):
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
We have created an ApiTestController similar to TestController inheriting from ApiController rather than from Controller.
However, the ApiTestController fails its test. I understand that the System.Web.Mvc.DependencyResolver class and the System.Web.Mvc.DependencyResolver.Current property are specific to Mvc. But does WebAPI have an equivalent?
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver.GetService does not work because the System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver instance is the parent container that I configured. It is not the child controller that was used to inject the ITestService into the constructor.
This user seems to have a similar problem: http://unitywebapi.codeplex.com/discussions/359413
But I feel that this probably has more to do with ASP.NET's WebAPI than it has to do with Unity.
Thanks
After looking over the source of http://unitymvc3.codeplex.com/ and http://unitywebapi.codeplex.com/ I created this class:
public class MyUnityDependencyResolver : Unity.Mvc3.UnityDependencyResolver, System.Web.Http.Dependencies.IDependencyResolver
{
public MyUnityDependencyResolver(IUnityContainer container)
: base(container)
{
}
public System.Web.Http.Dependencies.IDependencyScope BeginScope()
{
return this;
}
public void Dispose()
{
Unity.Mvc3.UnityDependencyResolver.DisposeOfChildContainer();
}
}
Configuration in gobal.asax.cs:
var myResolver = new MyUnityDependencyResolver(container);
System.Web.Mvc.DependencyResolver.SetResolver(myResolver);
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = myResolver;
Unity.Mvc3.UnityDependencyResolver uses HttpContext.Current.Items to manage child containers. MyUnityDependencyResolver may not be the most "correct" implementation of System.Web.Http.Dependencies.IDependencyResolver, but it seems to work so far.
I will mark this as the answer in a couple days if no one else has any better answers.
Unfortunately, when you call the GlobalConfiguration.Configuration.DependencyResolver.GetService, it completely ignores any scope and resolves using the outer non-child container which is around for the lifetime of the application. This is an issue with Web Api and makes it impossible to use constructor injection for per-request dependencies outside of controllers. Confusingly this is completely different behaviour from MVC as you say.
What you can do is use the GetDependencyScope() extension method off HttpRequestMessage. Anything you resolve using this will be in per request scope when using HierarchicalLifetimeManager in conjunction with Unity.WebApi. The request is available from action filters and handlers so may be a viable workaround.
Obviously this is pure service location rather than dependency injection which is far from ideal but I have not found another way to access per-request dependencies outside of controllers.
See this post for more info.
The DependencyResolver is not the right seam for dependency injection in ASP.NET WebAPI.
Mark Seemann has two really good posts on DI with WebAPI.
Dependency Injection and Lifetime Management with ASP.NET Web API
Dependency Injection in ASP.NET Web API with Castle Windsor
If you want to do it right you should have a look at them.

Resources