I got an error on the creation of an api controller due to that I didn't set up autofac for webapi.
However, I can't seem to catch the exception anywhere.
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Type 'MyWeb.Web.Controllers.MyController' does not have a default constructor
</ExceptionMessage>
<ExceptionType>System.ArgumentException</ExceptionType>
<StackTrace>
at System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
</StackTrace>
</Error>
I tried adding WebApi contrib for Elmah, then I added this:
config.Filters.Add(new Elmah.Contrib.WebApi.ElmahHandleErrorApiAttribute());
Didn't make elmah register the exception.
I added the following to global.asax:
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
}
Didn't make any difference at all.
How can I handle errors happening before the controllers are called?
I wonder if this exception is just being added to the content of the HttpResponseMessage but is not actually being thrown as an exception. When implementing a dependency resolver class for use during constructor instantiation, it usually makes sense to attempt resolution, catch exceptions and return null.
For example, in non-API MVC controllers I've often used something like this:
public class UnityDependencyResolver : IDependencyResolver
{
public readonly IUnityContainer Container;
public UnityDependencyResolver(IUnityContainer container)
{
Container = container;
}
#region IDependencyResolver Members
public object GetService(Type serviceType)
{
try
{
return Container.Resolve(serviceType);
}
catch (Exception ex)
{
if (ex.InnerException is TypeInitializationException)
throw ex.InnerException;
return null;
}
}
...
Related
I am registering my interface in App.config. But while resolving, I am getting the below exception.
Microsoft.Practices.Unity.ResolutionFailedException
HResult=0x80131500
Message=Resolution of the dependency failed, type = "Philips.DI.Interfaces.UW.DtoModel.IModelProvider`1[Philips.DI.UW.PatientOrchestrator.Interfaces.PatientScheduleDataModel]", name = "LoginPage".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, Philips.DI.Interfaces.UW.DtoModel.IModelProvider`1[Philips.DI.UW.PatientOrchestrator.Interfaces.PatientScheduleDataModel], is an interface and cannot be constructed. Are you missing a type mapping?
At the time of the exception, the container was:
Resolving Philips.DI.Interfaces.UW.DtoModel.IModelProvider`1[Philips.DI.UW.PatientOrchestrator.Interfaces.PatientScheduleDataModel],LoginPage
var proxy = container.Resolve<T>("LoginPage", new ResolverOverride[] {
new ParameterOverride("unityContainer", container),new ParameterOverride("serviceEndPoint", serviceEndPoint)});
public SyncProxy(IUnityContainer unityContainer, ServiceEndPoint serviceEndPoint) : base(unityContainer, serviceEndPoint)
{
_clientDataSyncWrapper = unityContainer.Resolve<ClientDataSyncWrapper>();
RegisterPushMessages();
}
[InjectionConstructor]
public SyncProxy(IUnityContainer unityContainer, string endPoint) : base(unityContainer, endPoint)
{
_clientDataSyncWrapper = unityContainer.Resolve<ClientDataSyncWrapper>();
RegisterPushMessages();
}
Why I'm I getting this error on Employee Controller rest of them are working perfectly
Here is my Employee Controller
public class EmployeeController : ApiController
{
#region Call service
private readonly IEmployeeServices _employeeServices;
public EmployeeController(IEmployeeServices employeeServices)
{
_employeeServices = employeeServices;
}
readonly IEmployeeServices employeeServices = new EmployeeServices();
public EmployeeController():base()
{
_employeeServices = employeeServices;
}
}
AND this is my perfectly Working Product Controller
public class ProductController : ApiController
{
#region Call service
private readonly IProductServices _productServices;
public ProductController(IProductServices productServices)
{
_productServices = productServices;
}
readonly IProductServices productServices = new ProductServices();
public ProductController()
{
_productServices = productServices;
}
}
Here is the stack trace
An error has occurred.An error occurred when trying to create a controller of type 'EmployeeController'. Make sure that the controller has a parameterless public constructor.System.InvalidOperationException at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()An error has occurred.Resolution of the dependency failed, type = "TheWork.Controllers.EmployeeController", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, BusinessServices.IEmployeeServices, is an interface and cannot be constructed. Are you missing a type mapping?
-----------------------------------------------
At the time of the exception, the container was:
Resolving TheWork.Controllers.EmployeeController,(none)
Resolving parameter "employeeServices" of constructor TheWork.Controllers.EmployeeController(BusinessServices.IEmployeeServices employeeServices)
Resolving BusinessServices.IEmployeeServices,(none)
Microsoft.Practices.Unity.ResolutionFailedException at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides)
at Microsoft.Practices.Unity.UnityContainerExtensions.Resolve(IUnityContainer container, Type t, ResolverOverride[] overrides)
at Unity.WebApi.UnityDependencyScope.GetService(Type serviceType)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func1& activator)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)An error has occurred.The current type, BusinessServices.IEmployeeServices, is an interface and cannot be constructed. Are you missing a type mapping?System.InvalidOperationException at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForAttemptingToConstructInterface(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
Update
Here is the Unity Configuration
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
System.Web.Mvc.DependencyResolver.SetResolver(new UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
RegisterTypes(container);
}
public static void RegisterTypes(IUnityContainer container)
{
ComponentLoader.LoadContainer(container, ".\\bin", "TheWork.dll");
ComponentLoader.LoadContainer(container, ".\\bin", "BusinessServices.dll");
ComponentLoader.LoadContainer(container, ".\\bin", "DataModel.dll");
}
}
Buried in the stack trace is the root cause of the issue:
InvalidOperationException - The current type,
BusinessServices.IEmployeeServices, is an interface and cannot be
constructed. Are you missing a type mapping?
----------------------------------------------- At the time of the exception, the container was: Resolving
TheWork.Controllers.EmployeeController,(none) Resolving parameter
"employeeServices" of constructor
TheWork.Controllers.EmployeeController(BusinessServices.IEmployeeServices
employeeServices) Resolving BusinessServices.IEmployeeServices,(none)
Microsoft.Practices.Unity.ResolutionFailedException at
Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object
existing, String name, IEnumerable1 resolverOverrides)
The issue is that the EmployeeController requires an instance of IEmployeeServices but Unity does not know what concrete type to instantiate. It looks like the implementation class is supposed to be registered by the call to ComponentLoader.LoadContainer(container, ".\\bin", "BusinessServices.dll"); but for some reason it is not being registered. It could be a bug in that code or perhaps the BusinessServices.dll is out of date and does not contain the IEmployeeServices definition.
It's hard to tell why IEmployeeServices is not registered without seeing all the code and runtime dependencies (because types are being dynamically loaded/registered).
Try this way :)
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IEmployeeServices >().To<EmployeeServices >().InRequestScope();
}
I am using Castle Windsor as an IoC with my MVC website project. I have it initialised it by doing the following:
new CastleInitialiser(new WindsorContainer().Install(FromAssembly.InDirectory(new AssemblyFilter(HttpRuntime.BinDirectory, "ProjectName*.dll"))));
And then in my constructor I have the following that registers my controllers:
Container.Register(CastleClasses.FromThisAssembly().IncludeNonPublicTypes().BasedOn<Controller>().LifestylePerWebRequest());
This all works fine but now when I hit a url that doesn't exist, I don't get a 404 error thrown - I get the following error message:
The IControllerFactory 'ProjectName.Website.Castle.IoC.CastleControllerFactory' did not return a controller for the name 'asdasdasasdasd'.
Where asdasdasasdasd is the name of the invalid url
Is there any way to get this so that it throws a 404 exception instead of a castle windsor exception?
In my CastleController class, I am able to throw the 404 like so:
public class WindsorControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, "page not found");
}
return (IController)container.Resolve(controllerType);
}
}
I'm having troubles handling all types of errors in ASP.NET WebAPI.
I've successfully handled exceptions thrown inside my action methods using an ExceptionFilter and 404 errors for invalid routes, invalid controller or action name. However, I'm struggling to handle the error where the controller and action are both found, but the parameters for model binding are incorrect types.
Here's my action, which is routed to /api/users/{id}.
[HttpGet]
public virtual TPoco Get(long id)
{
...
}
If I request the URL /api/users/notinteger, I get a 400 Bad Request error that is handled outside of my code:
{
Message: "The request is invalid.",
MessageDetail: "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int64' for method '___ Get(Int64)' in '___'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
}
How can I intercept this error and respond with my own error message? Preferably not in the controller itself as I'd like to handle several controllers in the same way.
I've tried using global.asax.cs's Application_Error event as per this question, but that doesn't seem to be called in this case.
It appears that these errors are added to the ModelState as model binding errors. The action selector selects the correct action and the action invoker invokes it without throwing any errors.
The workaround I came up with is to create an action invoker that checks the ModelState for errors. If it finds any, it passes the first one to the exception handling method used by my ExceptionFilter and ErrorController.
internal class ThrowModelStateErrorsActionInvoker : ApiControllerActionInvoker
{
public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
foreach (var error in actionContext.ModelState.SelectMany(kvp => kvp.Value.Errors))
{
var exception = error.Exception ?? new ArgumentException(error.ErrorMessage);
//invoke global exception handling
}
return base.InvokeActionAsync(actionContext, cancellationToken);
}
}
It's nasty, but it works. This has taken up most of my day and I'm just glad to have finally got somewhere.
I'd be interested to know what the consequences are to this. What else uses the ModelState errors in Web API? Could anyone add some possible flaws in this solution?
It will more better if you use the new WebApi 2.1 Global error handling as discussed here,
http://aspnetwebstack.codeplex.com/wikipage?title=Global%20Error%20Handling&referringTitle=Specs
http://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-21#global-error
If you are not willing to use WebApi 2.1 for a valid reason then you can try. (Note I have not tested but you can try). Create a custom action descriptor by inheriting with ReflectedHttpActionDescriptor and handle ExecuteAsync. This is what I mean,
public class HttpNotFoundActionDescriptor : ReflectedHttpActionDescriptor
{
ReflectedHttpActionDescriptor _descriptor;
public HttpNotFoundActionDescriptor(ReflectedHttpActionDescriptor descriptor)
{
_descriptor = descriptor;
}
public override Task<object> ExecuteAsync(HttpControllerContext controllerContext, IDictionary<string, object> arguments, CancellationToken cancellationToken)
{
try
{
return descriptor.ExecuteAsync(controllerContext, arguments, cancellationToken);
}
catch (HttpResponseException ex)
{
//..........................
}
}
}
public class HttpNotFoundAwareControllerActionSelector : ApiControllerActionSelector
{
public HttpNotFoundAwareControllerActionSelector()
{
}
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
HttpActionDescriptor decriptor = null;
try
{
decriptor = base.SelectAction(controllerContext);
}
catch (HttpResponseException ex)
{
var code = ex.Response.StatusCode;
if (code != HttpStatusCode.NotFound && code != HttpStatusCode.MethodNotAllowed)
throw;
var routeData = controllerContext.RouteData;
routeData.Values["action"] = "Handle404";
IHttpController httpController = new ErrorController();
controllerContext.Controller = httpController;
controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, "Error", httpController.GetType());
decriptor = base.SelectAction(controllerContext);
}
return new HttpNotFoundActionDescriptor(decriptor);
}
}
Note you need to override all the virtual methods.
I am using ServiceStack in standalone mode. It is now giving a TypeInitialzationException when executing Apphost.Start().
At the time, I was working on implementing some custom filters, but removing the annotation from the only filtered DTO class did not solve the problem.
The stack trace does not show any of my classes involved, and the failing class is the JsvReader which I don't use explicitly.
How can prevent this problem?
Note: I just used nuget to update all packages, so this is current as of now, 3.9.43 for all ServiceStack components.
Exception Detail
System.TypeInitializationException occurred
HResult=-2146233036
Message=The type initializer for 'ServiceStack.Text.Jsv.JsvReader`1' threw an exception.
Source=ServiceStack.Text
TypeName=ServiceStack.Text.Jsv.JsvReader`1
StackTrace:
at ServiceStack.Text.Jsv.JsvReader`1.GetParseFn()
at ServiceStack.Text.Jsv.JsvReader.GetParseFn(Type type)
at ServiceStack.ServiceModel.Serialization.StringMapTypeDeserializer..ctor(Type type)
at ServiceStack.ServiceHost.RestPath..ctor(Type requestType, String path, String verbs, String summary, String notes)
at ServiceStack.ServiceHost.ServiceController.RegisterRestPaths(Type requestType)
at ServiceStack.ServiceHost.ServiceController.RegisterCommon(Type serviceType, Type requestType, Type responseType)
at ServiceStack.ServiceHost.ServiceController.RegisterNService(ITypeFactory serviceFactoryFn, Type serviceType)
at ServiceStack.ServiceHost.ServiceController.Register(ITypeFactory serviceFactoryFn)
at ServiceStack.ServiceHost.ServiceManager.Init()
at ServiceStack.WebHost.Endpoints.Support.HttpListenerBase.Init()
at ArdWebServer.Program.Main(String[] args)
InnerException: System.TypeInitializationException
HResult=-2146233036
Message=The type initializer for 'ServiceStack.Text.Common.DeserializeSpecializedCollections`2' threw an exception.
Source=ServiceStack.Text
TypeName=ServiceStack.Text.Common.DeserializeSpecializedCollections`2
StackTrace:
at ServiceStack.Text.Common.DeserializeSpecializedCollections`2.get_Parse()
at ServiceStack.Text.Common.JsReader`1.GetCoreParseFn[T]()
at ServiceStack.Text.Common.JsReader`1.GetParseFn[T]()
at ServiceStack.Text.Jsv.JsvReader`1..cctor()
InnerException: System.NullReferenceException
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=ServiceStack.Text
StackTrace:
at ServiceStack.Text.PlatformExtensions.GenericTypeArguments(Type type)
at ServiceStack.Text.Common.DeserializeSpecializedCollections`2.GetGenericEnumerableParseFn()
at ServiceStack.Text.Common.DeserializeSpecializedCollections`2.GetParseFn()
at ServiceStack.Text.Common.DeserializeSpecializedCollections`2..cctor()
InnerException:
My App host
public class AppHost : AppHostHttpListenerBase
{
public AppHost() : base("IAM Tools Service Stack Host", typeof (Tims.Global).Assembly)
{
CatchAllHandlers.Add(
(httpMethod, pathInfo, filePath) =>
Tims.Support.StaticFileHandler.Factory(
Params.Instance.HttpDataDir,
"/",
pathInfo
)
);
}
public override void Configure(Funq.Container container)
{
SetConfig(new EndpointHostConfig()
{
DebugMode = true,
WriteErrorsToResponse = true
});
}
}