Working with WebApi in a Web Forms application - asp.net

I am trying to add WebApi in my Web Forms application (Visual Studio 2015, .NET 4.6). I added App_Start folder and WebApiConfig.cs in it as following (pretty much copied from an MVC app):
public class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
// Adding routes for WebApi controllers
RouteTable.Routes.MapHttpRoute(
name: "SearchApi",
routeTemplate: "api/search",
defaults: new { controller = "SearchController" }
);
}
}
Then, I created a folder Controllers/WebApi and added SearchController.cs:
namespace IdeaMaverick.Web.Controllers.WebApi
{
public class SearchController : ApiController
{
public IEnumerable<string> Get()
{
return new [] { "value1", "value2" };
}
}
}
But when I hit http://example.com/api/search in the browser, I get this error:
{"message":"No HTTP resource was found that matches the request URI
'http://www.example.com/api/search'.","messageDetail":"No type
was found that matches the controller named 'SearchController'."}
I'm obviously missing something but I can't figure out what.

I found the issue - in defaults for the route I had to specify the controller name omitting "Controller", so it has to be like
defaults: new { controller = "Search" }

Related

No file provider has been configured to process the supplied file

I am using Single Page Application with .Net core 2.2. I have following in my startup.cs.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa - fallback",
defaults: new { controller = "CatchAll", action = "Index" });
});
But having following
public class CatchAllController : Controller
{
public IActionResult Index()
{
return File("~/index.html", "text/html");
}
}
gives me following error.
No file provider has been configured to process the supplied file
I was following following article (one difference. article uses API project. I had taken angular project).
https://www.richard-banks.org/2018/11/securing-vue-with-identityserver-part1.html
I was just fighting this exact problem. Even though the File() method claims to take a "virtual path" I could never get it to load the file without the error you're getting. Here's what I ended up piecing together after reading a number of different posts.
[Route("[controller]")]
public class DocumentationController : ControllerBase
{
private readonly IHostingEnvironment _env;
public DocumentationController(IHostingEnvironment env)
{
_env = env;
}
[HttpGet, Route("apiReference")]
public IActionResult ApiReference()
{
var filePath = Path.Combine(_env.ContentRootPath,
"Controllers/Documentation/My Document.pdf");
return PhysicalFile(filePath, "application/pdf");
}
}

Default route when using ASP.NET MVC attribute routing

I'm using attribute routing with Web API, and everything works as expected if I request the URL /myapi/list with the following controller:
[RoutePrefix("myapi")]
public class MyController : ApiController
{
[HttpGet]
[Route("list")]
public async Task<string> Get()
{
// Return result
}
}
However, I would like my Get() method to be the default, i.e. when requesting the URL /myapi (without the /list part).
But if I remove the "list" part of the Route attribute like so...
[RoutePrefix("myapi")]
public class MyController : ApiController
{
[HttpGet]
[Route] // Default route
public async Task<string> Get()
{
// Return result
}
}
...I get a 403.14 error saying
"The Web server is configured to not list the contents of this
directory."
Any ideas of what might be causing this?
Thanks!
Edit: If I request the API controller using the default route pattern like /api/myapi, it maps to the Get() method as expected.
Default route is registered after the attribute routes:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Use
[Route("")]
for the default route
[RoutePrefix("myapi")]
public class MyController : ApiController
{
//GET myapi
[HttpGet]
[Route("")] // Default route
public async Task<string> Get() { ... }
}
Reference: Attribute Routing in ASP.NET Web API 2 : Route Prefixes
As pointed out by haim770 in the comments: the problem was that I had a physical folder with the same name as the route prefix.
Renaming either the folder or the route prefix solved the problem.
I guess an alternative would have been to tweak the route/handler order to ensure attribute routes take precedence over physical paths.

ASP.Net MVC Area not picking registered types

I am working on an ASP.Net application with a couple of MVC Areas defined. When I try to use dependency injection on a controller within an Area, I am getting the error below.
No parameterless constructor defined for this object.
I am using a Unity Container, and it appears the registered dependencies are not making it to the MVC Area.
Setup is pretty typical in the global.asax.cs:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(MyConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Are there an additional steps I am missing in order to inject dependencies in an MVC Area controller?
Additional Information
Here is the Area registration class:
public class MyAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "MyArea";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Unity Container:
public static class MyConfig{
public static IUnityContainer dependencyResolver { get; set; }
public static void Register(HttpConfiguration config)
{
// Create Unity container
var container = new UnityContainer();
// Register service types
container.RegisterType<ISomeService, SomeService>();
// omitted for brevity
// Create unity resolver
config.DependencyResolver = new UnityResolver(container);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
dependencyResolver = container;
}
Area Controller:
private ISomeServce SomeServce;
public LabController(ISomeServce someServce)
{
SomeServce = someServce;
}
Web API and MVC are two entirely different things. Your question originally stated you are using MVC, but your DI configurtion is only for Web API.
Configuration for MVC (and Areas)
As per the Dependency Injection Tutorial on MSDN, you are missing an important piece of your DI setup - namely, your Application_Start method is not setting up MVC to use DI. It is only set up to configure DI for Web API.
You need to either implement (or find an implementation based on) IControllerFactory or IDependencyResolver and set it at application startup in order to inject the controller dependencies.
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory(container));
// Or...
DependencyResolver.SetResolver(new MyDependencyResolver(container));

ASP.NET:New Action doesn't work

I have started a web api project and I am trying to add a new action to my existing controller. Here is my controller code and configurations:
namespace QAServices.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Title = "Home Page";
return View();
}
//[Route("Home/Welcome")] I have also tried this but it doesn't work.
public HttpResponseMessage Welcome()
{
HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
return response;
}
public ActionResult ProductPage()
{
return View();
}
}
}
RouteConfig
namespace QAServices
{
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 }
);
}
}
}
WebApiConfig
namespace QAServices
{
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));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { action = "GET", id = RouteParameter.Optional }
);
}
}
}
When I try to run my new action I am having following error:
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost:1095/Home/Welcome'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'Home'.
</MessageDetail>
</Error>
I have followed these but can't figure out what is wrong:
Attribute Routing in ASP.NET Web API 2
Getting Started with ASP.NET Web API 2 (C#)
Routing Basics in ASP.NET Web API
Getting Started with ASP.NET MVC 5
Your code works for me. I get the response StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: , Headers: { }.
Your HomeController is just a regular MVC controller. However, the response you are getting appears to be a WebApi response. So it seems to indicate that the request is being routed to an ApiController.
Is it possible you have an ApiController in your project that is decorated with [RoutePrefix("Home")] which has no Welcome action method?
Also, if you have a mix of ApiController and MVC Controller, I would leave the default WebApiConfig route template of api/{controller}/{id} or at least differentiate if from that used for MVC controller.
Change public HttpResponseMessage Welcome() to public ActionResult Welcome(). In ASP.NET MVC controller actions need to return ActionResult.

Asp.net web api routing to be like mvc site

How can I add a route so that my controllers will work similar to a mvc web appliation.
Because the default way that they have configured the routes will end up with you having so many controllers.
I just want to have a controller called Auth,
and then in my web API be able to call api/auth/login or api/auth/logout etc.
Because with the default routing I will have to create a controller for login and one for logout.
So then I would have my Controller like so:
public class AuthController : ApiController
{
[HttpPost]
public IEnumerable<string> Login()
{
return new string[] { "value1", "value2" };
}
[HttpGet]
public HttpMessageHandler Logout()
{
return new HttpMessageHandler.
}
}
The default Web API route uses the http method to determine the action to select. For example POST api/auth would look for an action named Post on AuthController.
If you want to use RPC style routing (like MVC) you need to change the default route to:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Now POST api/auth/login will look for an action named Login on AuthController.

Resources