Ensure that HttpConfiguration.EnsureInitialized()

做~自己de王妃 提交于 2019-11-27 06:30:58
Ian Mercer

See @gentiane's answer below for the correct way to handle this now.

At the end of the Application_Start method in Global.Asax.cs try adding:-

GlobalConfiguration.Configuration.EnsureInitialized(); 

If you do it at the end of Application_Start it will be too late, as WebApiConfig.Register has been called.

The best way to resolve this is to use new initialization method by replacing in Global.asax :

WebApiConfig.Register(GlobalConfiguration.Configuration);

by

GlobalConfiguration.Configure(WebApiConfig.Register);
Jeff Yates

I actually got this error when I was using Attribute Routing within my WebApi.

I had

[Route("webapi/siteTypes/{siteTypeId"]

instead of

[Route("webapi/siteTypes/{siteTypeId}"]

for my route and got this error. I had simply missed out the closing curly bracket. Once I added it back in, this error didn't occur again.

tField

This is old, but is the first result on google when searching for this error. After quite a bit of digging I was able to figure out what was going on.

tldr:
All GlobalConfiguration.Configure does is invoke your action and call EnsureInitialized(). config.MapAttributeRoutes() must be called before EnsureInitialized() since EnsureInitialized only runs once.

Meaning: if you're coming from an existing Mvc project, all you have to do is:

  1. Add GlobalConfiguration.Configuration.EnsureInitialized(); to the bottom of your Application_Start method.

OR

  1. Move your entire configuration into a single call to GlobalConfiguration.Configure:
GlobalConfiguration.Configure(config => 
{
    WebApiConfig.Register(config);
    config.MapAttributeRoutes();
    ...
});

Digging Deeper

HttpConfiguration.Configuration has an "Initializer" property defined like this:

public Action<HttpConfiguration> Initializer;

HttpConfiguration.EnsureInitialized() runs this action and sets _initialized to true

public void EnsureInitialized()
{ 
    if (_initialized)
    {
        return;
    }
    _initialized = true;
    Initializer(this);            
}

HttpConfiguration.MapAttributeRoutes calls internal method AttributeRoutingMapper.MapAttributeRoutes which sets HttpConfiguration.Initializer

public static void MapAttributeRoutes(...)
{
    RouteCollectionRoute aggregateRoute = new RouteCollectionRoute();
    configuration.Routes.Add(AttributeRouteName, aggregateRoute);

    ...

    Action<HttpConfiguration> previousInitializer = configuration.Initializer;
    configuration.Initializer = config =>
    {
        previousInitializer(config);
        ...
    };
}

GlobalConfiguration.Configure runs EnsureInitialized immediately after invoking your action:

public static void Configure(Action<HttpConfiguration> configurationCallback)
{
    if (configurationCallback == null)
    {
        throw new ArgumentNullException("configurationCallback");
    }

    configurationCallback.Invoke(Configuration);
    Configuration.EnsureInitialized();
}

Don't forget, if you run in to a wall, the source for asp.net is available at http://aspnetwebstack.codeplex.com/SourceControl/latest

I've had a related issue. Sometimes calling GlobalConfiguration.Configure multiple times triggers this error. As a workaround, I've put all configuration initialization logic in one place.

For me, the problem was that I was trying to use named parameters for query string fields in my routes:

[Route("my-route?field={field}")]
public void MyRoute([FromUri] string field)
{
}

Query string fields are automatically mapped to parameters and aren't actually part of the route definition. This works:

[Route("my-route")]
public void MyRoute([FromUri] string field)
{
}

Although the above answer works if incase that is not set, In my case this stuff was set already. What was different was that, for one of the APIs I had written, I had prefixed the route with a / . Example

[Route("/api/abc/{client}")] 

.Changing this to

[Route("api/abc/{client}")]

fixed it for me

IF THIS ERROR SEEMS TO HAVE COME "OUT OF NOWHERE", i.e. your app was working perfectly fine for a while, ask yourself: Did I add an action to a controller or change any routes prior to seeing this error?

If the answer is yes (and it probably is), you likely made a mistake in the process. Incorrect formatting, copy/pasting an action and forgetting to make sure the endpoint names are unique, etc. will all end you up here. The suggestion that this error makes on how to resolve it can send you barking up the wrong tree.

Call

GlobalConfiguration.Configuration.MapHttpAttributeRoutes();

before

GlobalConfiguration.Configure(c => ...);

completes its execution.

I got this error when the version of Newtonsoft.Json was different in my main project compared to the helper project

One typically gets this exception when route templates in "Attribute Routing" are not proper.

For example, i got this when i wrote the following code:

[Route("{dirName:string}/contents")] //incorrect
public HttpResponseMessage GetDirContents(string dirName) { ... }

In route constraints syntax {parameter:constraint}, constraint by default is of type string. No need to mention it explicitly.

[Route("{dirName}/contents")] //correct
public HttpResponseMessage GetDirContents(string dirName) { ... }

I began getting this error one day. After I'd altered our app to call EnsureInitialized() I was able to see the root cause.

I had a custom attribute, a filter, on an action. That attribute class had had a breaking change made in the NuGet package in which it lives.

Even though I'd updated the the code and it all compiled, the local IIS worker was loading an old DLL and not finding a class member during initialization, reading attributes on actions etc.

For some reason (possibly due to order/when our logging is initialized), this error was not discoverable, possibly leaving the WebAPI in a strange state, until I'd added EnsureInitialized() which caught the exception and surfaced it.

Performing a proper bin and obj clean via a handy script resolved it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!