Web api call works locally but not on Azure - asp.net-web-api

I have same issue as per following questions and tried answer but never resolve issue
Web api interface works locally but not on Azure
Web API interface works locally but gets 404 after deployed to Azure Website
and many more similar type of...
When i tried to call api it says 404 Not Found
my WebApi.config file
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "versionApi",
routeTemplate: "api/{version}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
API Controller
[Authorize]
[RequiresSSL]
[RoutePrefix("api/v2/Configuration")]
public class ConfigurationAPIv2Controller : ApiController
{
[Dependency]
public IConfigurationServicev2 configurationService { get; set; }
[Dependency]
public IAccountService accountService { get; set; }
#region testapi
[Route("getstring")]
[HttpGet]
public IHttpActionResult getstring()
{
return Ok("Success");
}
[Route("putstring")]
[HttpPut]
public IHttpActionResult putstring()
{
return Ok("Success");
}
#endregion
And Folder Structure is like :
i got follwowing issue for both get and Put method

404 error might caused by route issue. Since you are using route attribute for your Web API. Please make sure GlobalConfiguration.Configure(WebApiConfig.Register); is above other code.
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
And config.MapHttpAttributeRoutes(); code is above other routes configuration.
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "versionApi",
routeTemplate: "api/{version}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
In addition, try to delete following code in your Controller to test whether it is related to the dependent injection module.
[Dependency]
public IConfigurationServicev2 configurationService { get; set; }
[Dependency]
public IAccountService accountService { get; set; }
If it also can't work for you. You could get the detail error message from web server after setting IncludeErrorDetailPolicy property in WebApiConfig class.
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;

Visual Studio does not add a default.html page to wwwroot and IIS does.
Just add default.html page to wwwroot in your project, then re-deploy to Azure.

Related

Web API error - Server Error in '/api' Application

After publishing Web API to IIS, which is a child of an AngularJs IIS site, I can reach 'https://localhost/api' and see all endpoints; but when I try to reach some specific endpoint with a GET request, I get an error
Server Error in '/' Application
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
[RoutePrefix("api/branches")]
public class BranchesController : ApiBaseController
{
[HttpGet]
[Route("getBranches")]
public async Task<JsonResult<List<BranchDto>>> GetActiveBranches()
{
var branches = new List<BranchDto>();
var models = await WarehouseUnitOfWork.BranchRepository.GetActiveBranches();
if (models != null && models.Count > 0)
{
branches.AddRange(AutoMapper.Mapper.Map<List<Branch>, List<BranchDto>>(models));
}
return Json(branches, new JsonSerializerSettings
{
ContractResolver = new WarehouseCustomContractResolver()
});
}
}
Any ideas how to solve this?
The solution for my case was to deploy the Frontend into the main IIS site, and inside it create an application called v1 for the Backend.
Then within my angularJS I defined the Production app to make the http requests to /v1/api instead of /api.

Web API routing in Sitecore 8.2

I migrated a sitecore 7.2 application to sitecore 8.2 using the express migration tool. After the migration Web API routing stopped working. I'm using below given method to map the routing
[UsedImplicitly]
public class ConfigRegister
{
/// <summary>
/// Startup method to bind all configurations for site core pipeline.
/// </summary>
/// <param name="args"></param>
public virtual void Process(PipelineArgs args)
{ RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
Then registering it using following code snippet
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ControllersApi",
routeTemplate: "WebApi/CustomerPortal/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
I'm getting error A route named 'MS_attributerouteWebApi' is already in the route collection. Route names must be unique.
Parameter name: name.
But when I comment the line
config.MapHttpAttributeRoutes();
I'm getting error
{"Message":"An error has occurred.","ExceptionMessage":"The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.","ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Web.Http.Routing.RouteCollectionRoute.get_SubRoutes()\r\n at System.Web.Http.Routing.RouteCollectionRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request)\r\n at System.Web.Http.WebHost.Routing.HttpWebRoute.GetRouteData(HttpContextBase httpContext)"}
Your help to solve this issue is highly appreciated
I assume you have this under the initialize pipeline, correct?
This is what we've done before and works on 8.2:
public void Process(PipelineArgs args)
{
HttpConfiguration httpConfig = GlobalConfiguration.Configuration;
httpConfig.Routes.MapHttpSessionRoute("WebApiRoute", "webapi/{controller}/{action}/{id}", true, new { id = RouteParameter.Optional });
}
If the above doesn't work,try this (per Habitat):
public void Process(PipelineArgs args)
{
RouteTable.Routes.MapHttpRoute("Feature.Demo.Api", "api/demo/{action}", new
{
controller = "Demo"
});
}

Adding Web API 2 manually - getting 404

I've returned to a solution that was put on hold and when I originally created it, I didn't tick Web API. I've added it manually but when I call my URL i'm recieving a 404. I suspect I am missing some configuration but I'm not sure.
My web api controller
[RoutePrefix("search")]
public class SearchController : BaseWebApiController
{
private readonly IAmtProxy _amtProxy;
public SearchController(IAmtProxy amtProxy)
{
this._amtProxy = amtProxy;
}
[HttpGet]
[Route("supportticket/{id}")]
public HttpResponseMessage GetSupportTicket(int id)
{
try
{
var result = _amtProxy.GetSupportTicketById(id);
return GetResponse(result);
}
catch (Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e.Message);
}
}
[HttpGet]
[Route("supportticket")]
public HttpResponseMessage GetAllSupportTickets()
{
try
{
var result = _amtProxy.GetAllSupportTickets();
return GetResponse(result);
}
catch (Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e.Message);
}
}
}
Example of url that returns 404
http://localhost:60541/search/supporticket/1
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /search/supporticket/1
Application_start in global.asax.cs has this code:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Bootstrapper.Initialise();
}
I also have my WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional});
}
}
Finally with nuget I got web api 2 and it installed successfully.
Does anyone know what I could be missing?
Your config looks fine.
It appears that you have misspelled the url:
http://localhost:60541/search/supporticket/1
It should be:
http://localhost:60541/search/supportticket/1
According to your implementation:
[Route("supportticket/{id}")]

web api - message handler attribute routing

Does anyone know whether message handler can work simultaneously with attribute routing in Web API 2.x? I got a custom message handler to work using conventional routing, then after adding attribute routing, it stops working. I am not sure whether it's not supported or if I had misconfigured something. Any help is greatly appreciated.
1) before attribute routing
--- WebApiConfig.cs code snippet (simplified)----
config.Routes.MapHttpRoute(
name:"DefaultApi",
routeTemplate: "api/{controller}",
defaults: null,
constraints: null,
handler: my-message-handler-object
);
--- MyController.cs code snippet (simplified)----
public class MyController : ApiController
{
[HttpGet]
public IHttpActionResult CheckInServices(...)
{
...
}
}
2) after attribute routing
--- WebApiConfig.cs code snippet (simplified)----
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name:"DefaultApi",
routeTemplate:"api/vendor",
defaults: new { controller = "Users" },
constraints: null,
handler: my-message-handler-object
);
}
--- MyController.cs code snippet (simplified)----
[RoutePrefix("api/vendor/{vendorID:long}/service")]
public class MyController : ApiController
{
[HttpPost]
[Route("{serviceID:long}")]
public IHttpActionResult CheckInServices(...)
{
...
}
}
Thanks,
Cody
Global message handlers will work - just set it up on start up.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new YourAuthenticationHandler());
}
}
I'm unsure if per route Message Handlers work with Attribute Routing.

WebApi Controller Get Action Doesn't Work

I'm having trouble with one of my WebApi2 controllers. While writing tests I've discovered the Get() is never hit instead it returns a 301 followed by 403. Oddly if I hit Get(id) the second action speaks up and does its job, but I can never hit the Get() action. If I rename the controller it works properly, but sadly, I cannot rename ModelsController to ModelController as I would like since there is an existing user base expecting that name. This is a rewrite of an existing Api that was done in MVC2 I think. All the other controllers work great, just not this one.
Any thoughts as to how to debug this? Or what I may have missed?
Other notes:
The routing configuration is default.
There is no other ModelsController to be found
Below is a simplified version of my code, and the problem remains...
using System.Collections.Generic;
using System.Web.Http;
using TW.Api.Business.Services.Models;
namespace TW.Api.Business.Services.Controllers
{
public class ModelsController : ApiController
{
public string Get()
{
return null;
}
public string Get(string id)
{
return null;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Routing;
namespace tw.api.business
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "Api_GetWithChild",
routeTemplate: "{controller}/{id}/{action}/{childId}",
defaults: new { id = RouteParameter.Optional, action = "Get", childId = RouteParameter.Optional },
constraints: new { httpMethod = new HttpMethodConstraint("GET") });
config.Routes.MapHttpRoute(
name: "Api_Post",
routeTemplate: "{controller}/{id}/{action}/{childId}",
defaults: new { id = RouteParameter.Optional, action = "Post", childId = RouteParameter.Optional },
constraints: new { httpMethod = new HttpMethodConstraint("POST") });
config.Routes.MapHttpRoute(
name: "Api_Put",
routeTemplate: "{controller}/{id}/{action}/{childId}",
defaults: new { id = RouteParameter.Optional, action = "Put", childId = RouteParameter.Optional },
constraints: new { httpMethod = new HttpMethodConstraint("PUT") });
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
// To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
// For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
//config.EnableQuerySupport();
// To disable tracing in your application, please comment out or remove the following line of code
// For more information, refer to: http://www.asp.net/web-api
//config.EnableSystemDiagnosticsTracing();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace tw.api.business
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
Looking at your route config, there are a few issues
The constrained routes are not really necessary
The id being optional in a middle of a route pattern doesn't really work, your optional items should come at the end.
When creating methods for web-API end-points, you must follow some naming conventions for automatically mapping of method-to-api. Or you can override that using HTTP action and Route attributes
Follow either of the following arrangements (note the 'Model' and 'Models' in method names):
public class ModelsController : ApiController
{
public string GetModels()
{
return null;
}
public string GetModel(int id)
{
return null;
}
}
Or, use the route attributes:
public class ModelsController : ApiController
{
[HttpGet]
[Route("api/Models")]
public string GetModels()
{
return null;
}
[HttpGet]
[Route("api/Models/{id}")]
public string GetModel(string id)
{
return null;
}
}
Ref: Routing and Action Selection

Resources