Good day, I am in a bit of a problem with my hosted ASP.NET WebAPI and MVC app hosted on IIS on a web server (MS Windows Server 2016). This is a basic website and includes an API in the same project. The web app has Areas and I suspect this is the problem. Periodically the website (Areas and API) goes down, the weird thing is that the views not under areas work fine, and the ones under areas and API stop working. There is no customization from the boiler template code for creating areas and so forth. I have also profiled requests coming in, but these are all basic calls with not a lot of data. I cannot see anything in the Event Viewer or IIS Logs, please does anyone have a suggestions?
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);//WEB API Registration
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
DiConfig.Register();
//Enable Claims Anti Forgery
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
}
Routing Config:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.RouteExistingFiles = true;
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Exports", action = "Index", id = UrlParameter.Optional },
namespaces:new[] {""}
);
}
}
WebAPIConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
//config.MessageHandlers.Add(new TokenValidationHandler());
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/v1/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
//Configure to use XmlSerializer so you don't have to configure namespace in xml request
config.Formatters.XmlFormatter.UseXmlSerializer = true;
config.Formatters.XmlFormatter.SetSerializer<CertificateRequest>(new XmlSerializer(typeof(CertificateRequest)));
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));
//Ignore Self Looping References
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
//WEB API Throttling
config.MessageHandlers.Add(new ThrottlingHandler()
{
Policy = ThrottlePolicy.FromStore(new PolicyConfigurationProvider()),
Repository = new CacheRepository()
});
//
config.Services.Add(typeof(IExceptionLogger), new ElmahExceptionLogger());
}
}
Related
I have created a C# Web API and I am able to access it on local host but post server deployment I am receiving 404 not found error.
Postman shows error - 'The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.'.
I have published the code using visual studio and then uploaded the files using file-zilla to the server.
The folder on the server is marked as an application.
I am able to access a sample html file present in the folder but not the api itself.
The Global.asax.cs has below code -
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);
GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
}
}
RouteConfig.cs
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 }
);
}
WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Filters.Add(new BasicAuthenticationAttribute());
}
I am trying to invoke the normal get method
[BasicAuthentication]
[HttpGet]
[Route("api/getmethodapi")]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
The URI i am accessing is something like -
https://mysampleapp.com/sampleFolder/api/getmethodapi
I am able to get the values using Postman as well as with C# console application on local host.
Any help/suggestions would be appreciated.
I am trying to build a microservice web content api which is a simple ASP.NET MVC Web Project.
My Question is, how can I create a main page which is documentation for routes just like swagger for WEB APIs
I have a RouteConfig.cs like below
routes.MapRoute(RouteNames.X,
"X/{action}",
new { controller = "XController", action = "XAction" });
routes.MapRoute(RouteNames.Y,
"Y/{action}",
new { controller = "YController", action = "YAction" });
routes.MapRoute(RouteNames.Z,
"Z/{action}",
new { controller = "ZController", action = "ZAction" });
First...add the WebApiConfig.cs file in App_Start folder and above code use in asp.net mvc not for asp.net mvc webapi. Currently you are mapping the wrong thing. Below I have the sample code & link.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Getting Started with ASP.NET Web API 2 (C#)
For supportability reasons I'm porting an application from .Net Core with ReactJs to .Net MVC.
This also uses Redux for state handling.
This seemed to be going ok but for some reason the WebAPI calls all fail with 404 errors.
I'm pretty sure the routing is correct as per the failing calls but clearly something is getting lost somewhere.
The default MVC controller that was added as an entry point works fine, it's just the ported WebAPI controllers that seem to fail.
I'm not allowed to post the entire code for commercial reasons but this is what the controller and one of the actions in question looks like:
namespace Api.Controllers
{
/// <summary>
/// Account management.
/// </summary>
[Authorize]
[System.Web.Http.RoutePrefix("api/account")]
public class AccountController : ApiController
{
// <snip>
/// <summary>
/// Current logged in account.
/// </summary>
// GET api/Account/UserInfo
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[System.Web.Http.Route("userinfo")]
public async Task<UserInfoViewModel> GetUserInfo()
{
ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
var userName = User.Identity.GetUserName();
var account = new AccountRepresentation(await _context
.Accounts
.SingleOrDefaultAsync(acc => acc.Email == userName));
return new UserInfoViewModel
{
Account = account,
UserName = User.Identity.GetUserName(),
Email = User.Identity.GetUserName(),
HasRegistered = externalLogin == null,
LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null,
Roles = await UserManager.GetRolesAsync(User.Identity.GetUserName())
};
}
// </snip>
}
}
(snip comments added by me)
Notice the routing attributes - it's a bit over the top as I'm trying everything, but as far as I can tell this should be ok.
However in the browser console I'm seeing this:
Failed to load resource: the server responded with a status of 404
(not found) http://localhost:49690/api/account/userinfo
The port number is correct for the default controller so unless it's different for the other controllers for some reason, this should be ok as well.
I've been playing with the RouteConfig.cs file which currently looks as follows:
namespace Api
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "Api.Controllers" }
).DataTokens.Add("area", "UI");
routes.MapRoute(
name: "api",
url: "api/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "Api.Controllers" }
).DataTokens.Add("area", "UI");
}
}
}
The WebApiConfig file looks as follows:
namespace Api
{
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 }
);
// Web API configuration and services
// Web API routes
// config.MapHttpAttributeRoutes();
// Configure Web API to use only bearer token authentication.
// config.SuppressDefaultHostAuthentication();
// config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
//config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
//config.Routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{controller}/{id}",
// defaults: new { id = RouteParameter.Optional }
//);
}
}
}
Application_Start() is like this:
namespace Api
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
//UnityConfig.RegisterComponents();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
log4net.Config.XmlConfigurator.Configure();
}
}
}
What else could be missing or wrong that is preventing the API actions being found?
(Let me know if any other code would be helpful)
Other details:
Visual Studio version: Enterprise 2015 update 3
.NET version: 4.6.1
In .Net Core, attribute routing is now enabled by default. However, in MVC5, you are need to set it up. In your route config, add this:
routes.MapHttpAttributeRoutes();
Note that for normal MVC (i.e. not WebAPI) you need this command instead:
routes.MapMvcAttributeRoutes();
Note: MapHttpAttributeRoutes is an extension method in System.Web.Http so you will need a using System.Web.Http; statement.
if you Porting .net Core application from .net mvc you have add WebApiConfig file and register in global file. and it should be like this. First use Route Attribute because you have use Attribute routing.
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 }
);
}
I'm having trouble getting WEBAPI 2 attribute routing to work. The routing scheme I'm looking for is /api/{product}/{controller}/{id-optional}, so like /api/Vision/IdCard. The controllers are in an area and are set up like this:
namespace DataServices.Controllers.Vision
{
[RoutePrefix("api/vision")]
public class IdCardController : BaseApiController
{
[System.Web.Mvc.RequireHttps]
[Route("idcard")]
public IdCardViewModel Get(HttpRequestMessage request)
{...}
Whenever I do a get to this, I get a 404. I included the namespace as the area is in it's own namespace. Are areas supported in WEBAPI attribute routing?
EDIT: WebApiConfig looks like this:
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
You need to get the HttpConfiguration instance from the GlobalConfiguration object and call the MapHttpAttributeRoutes() method from inside the RegisterArea method of the AreaRegistration.cs.
public override void RegisterArea(AreaRegistrationContext context)
{
GlobalConfiguration.Configuration.MapHttpAttributeRoutes();
//... omitted code
}
This must be done for each Area.
Finally you must in the 'WebApiConfig' remove "config.MapHttpAttributes()" method or you will get duplicate exception.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
//config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Is the project a MVC project from start? Then I think you should remove the "ApiAreaRegistration.cs" file created when you created the area. It's found in the root of the your Api area and it will conflict with your attribute routes as it will match on a MVC (not WebApi) route like "api/{controller}/{action}/{id}" before it finds your specific routes.
Hope it helps!
Area functionality not available in Asp.Net Web API project, and its harder to maintain with custom way like Namespace based controller.
I have checked many problems with namespace based controller and routing, like single action method is accessible by namespace based routing as well as default routing.Thus custom implementation does not mitigate our requirements.
To resolve this issue we can use simple way to manage controllers routing as :
//Remove default routing registration
/*config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);*/
And use just attribute based routing only, like
[RoutePrefix("api/user/home")]
public class UserHomeController : ApiController
{
[Route]
public string Get()
{
return "Test user GET";
}
}
And for different area/module controller
[RoutePrefix("api/admin/home")]
public class AdminHomeController : ApiController
{
[Route]
public string Get()
{
return "Test admin GET";
}
}
Advantages with this approach are:
No need of custom logic like namespace based area, custom routing handler, so its better way to code.
Just need to add attribute [Route] in action to availability in API
Try play with initialization order in Application_Start
Thus:
//Config WebAPI(2) where you call config.MapHttpAttributeRoutes();
GlobalConfiguration.Configure(WebApiConfig.Register);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Order is very important (if i reverse areaRegistration with WebApiConfig => WebAPI 2 attributeRouting won't work
I'm trying to register multiple routes for Web Pages and for Web API. Here's my config's:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Registration Courses SPA",
url: "Registration/Courses",
defaults: new {controller = "Registration", action = "Index"});
routes.MapRoute(
name: "Registration Instructors SPA",
url: "Registration/Instructors",
defaults: new { controller = "Registration", action = "Index" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
and
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate:"api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Here's how I register them in Global.asax
RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configure(WebApiConfig.Register);
The problem is that Web API routing not working, I'm getting 404 error, unless I register WebAPI routes first then ASP.NET MVC routes not working and Web API routes working.
Like #ChrFin stated in his comments, if you register the Web API routes first your MVC routes should still work because the default Web API route begins with "api".
I had the same problem but it was because we changed the routeTemplate of the default Web API route to {controller}/{id} because we wanted that to be the default because the purpose of our app is to be an api for other apps. In our Global.asax file the Web API routes are registered before the MVC routes, which is the default for any new Web API application. Because "/anything" matches the default Web API route, route handling stops so our MVC routes never get a chance to get matched.
The key point is that route handling stops if a route gets matched - even if there's no matching controller.
To solve our problem we prefixed our MVC routes with "mvc" and registered our MVC routes before the Web API routes.