Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net Web Api - ApiExplorer does not contain any ApiDescriptions

I am trying to implement an Options method in a controller of my web service that will return a message containing the valid HTTP methods for the URI endpoint associated with the controller. My Options method looks something like this:

public HttpResponseMessage Options()
{
    var resp = new HttpResponseMessage();
    resp.Content = new StringContent("");

    var apiExplorer = GlobalConfiguration.Configuration.Services
        .GetApiExplorer();

    foreach (ApiDescription api in apiExplorer.ApiDescriptions)
    {
        resp.Content.Headers.Add("Allow", api.HttpMethod.Method);
    }

    return resp;
}

I have tried the above method in a brand-new Web Api project (implication: unaltered routing) inside of a controller with Get, Post, and Delete methods. As expected, a response with "Allow: GET, POST, DELETE" is returned. I am having trouble, however, adding this to a larger project that I am working on. In the larger project, the ApiDescriptions list within ApiExplorer does not contain any elements. Why is this? I suspect it is due to the custom routing that has been implemented, although the only basis for that suspicion is the following link:

http://forums.asp.net/t/1821651.aspx/1

Has anybody else experienced this empty ApiDescription list? If so, did you find a remedy?

Note: I am using MCV 4 RC

like image 723
Jeremy G Avatar asked Aug 16 '12 18:08

Jeremy G


3 Answers

If you use Glimpse, you might have to disable it's route inspector:

<glimpse defaultRuntimePolicy="On" endpointBaseUri="~/Glimpse.axd">
  <logging level="Off" />
  <tabs>
    <ignoredTypes>
      <add type="Glimpse.AspNet.Tab.Routes, Glimpse.AspNet" />
    </ignoredTypes>
  </tabs>
  <inspectors>
    <ignoredTypes>
      <add type="Glimpse.AspNet.Inspector.RoutesInspector, Glimpse.AspNet" />
    </ignoredTypes>
  </inspectors>
</glimpse>

Glimpse creates RouteProxies that break enumeration in HostedHttpRouteCollection: https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Http.WebHost/Routing/HostedHttpRouteCollection.cs

I know the link is for mono but the same is true for standard .Net.

like image 185
Axel Wilczek Avatar answered Nov 13 '22 08:11

Axel Wilczek


You should look to upgrade to the RTM of WebApi that was released yesterday and then check out the newly released ASP.NET WebApi Help Page (Preview) that was also released yesterday.

This package automatically generates help page content for Web APIs on your site. Visitors to your help page can use this content to learn how to call your web APIs. Everything generated by the help page is fully customizable using ASP.NET MVC and Razor.

It is implementing the ApiExplorer under the covers.

like image 34
Paige Cook Avatar answered Nov 13 '22 08:11

Paige Cook


The solution for this problem is to comment in ProjectName\Areas\HelpPage\Controllers\HelpController.cs the constructors like this:

    public class HelpController : Controller
        {
            private const string ErrorViewName = "Error";

    //        public HelpController()
    //            : this(GlobalConfiguration.Configuration)
    //        {
    //        }

    //        public HelpController(HttpConfiguration config)
    //        {
    //            Configuration = config;
    //        }

            /// <summary>
            /// GlobalConfiguration By default
            /// </summary>
            protected static HttpConfiguration Configuration
            {
                get { return GlobalConfiguration.Configuration; }
            }

            public ActionResult Index()
            {
                ViewBag.DocumentationProvider = Configuration.Services.GetDocumentationProvider();
                return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
            }
....

The default constructor is not called;

The second method is to inject the default constructor by add this attribute [InjectionConstructor] on default constructor like this:

public class HelpController : Controller
    {
        private const string ErrorViewName = "Error";

         [InjectionConstructor]
        public HelpController()
            : this(GlobalConfiguration.Configuration)
        {
        }

        public HelpController(HttpConfiguration config)
        {
            Configuration = config;
        }

        /// <summary>
        /// GlobalConfiguration By default
        /// </summary>
        protected static HttpConfiguration Configuration { get; private set; }
....
like image 1
TotPeRo Avatar answered Nov 13 '22 07:11

TotPeRo