I have my WebApiConfig setup like this:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
I have registered the route in Global.asax as follows:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
WebApiConfig.Register(GlobalConfiguration.Configuration);
}
My Web api controller class looks like this:
[RoutePrefix("api/upload")]
public class UploadController : ApiController
{
[HttpGet]
[Route("")]
public string Upload()
{
return "hello";
}
}
I'm making call to the Web Api action in fiddler as shown in the image below:
I'm getting 404 Not Found not found error when I send the request. What am I doing wrong?
Try to configure Web API before MVC route mappings:
protected void Application_Start()
{
WebApiConfig.Register(GlobalConfiguration.Configuration);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
What I believe is happening is that the framework is trying to map your route to an MVC one. It is assuming that this URI localhost:8170/api/upload is referring to an MVC controller called Api with an action named Upload.
Registering Web API routes before MVC will allow the framework to match routes starting with api/ to the correct ApiController.
Related
In a single Console Application I must self-host both a SignalR Server and a Web Api.
I'm using this code
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Hosting;
using Owin;
using Microsoft.Owin.Cors;
using System.Web.Http;
using System.Net.Http;
namespace SignalRSelfHost
{
class Program
{
static void Main(string[] args)
{
string url = "http://localhost:8080";
using (WebApp.Start(url))
{
Console.WriteLine("Server running on {0}", url);
//////////
// Create HttpCient and make a request to api/values
HttpClient client = new HttpClient();
var response = client.GetAsync(url + "/api/values").Result;
Console.WriteLine(response);
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
Console.ReadLine();
//////////
Console.ReadLine();
}
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
////////
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
app.UseWebApi(config);
/////////
app.MapSignalR();
}
}
public class MyHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);
}
}
}
and I've entered the following commands:
Install-Package Microsoft.AspNet.SignalR.SelfHost
Install-Package Microsoft.Owin.Cors
Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
Now the SignalR server works OK, but not the WebApi: it gives me "No HTTP resource was found that matches the request URI 'http://localhost:8080/api/values'". My controller class is the following:
namespace SignalRSelfHost
{
class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
}
Anyone can help me?
Set your ValuesController from private to public and it should work.
Similar to SO ASP.NET MVC: Many routes -> always only one controller:
O have a .net 4.7 MVC project project
my config route are as follows (following from the above post)
config.Routes.MapHttpRoute(
name: "AllRoutes",
routeTemplate: "{*url}",
defaults: new
{
controller = "base",
});
my base controller in my .net 4.7 project
public class BaseController : ApiController
{
[HttpGet]
public IHttpActionResult Get(HttpRequestMessage request)
{
return Ok();
}
[HttpPost]
public IHttpActionResult Post(HttpRequestMessage request)
{
return Ok();
}
[HttpPut]
public IHttpActionResult Put(HttpRequestMessage request)
{
return Ok();
}
[HttpDelete]
public IHttpActionResult Delete(HttpRequestMessage request)
{
return Ok();
}
}
now I'm porting my project into a .NET Core 2.0
I can't seem to setup the same thing
my config in the .net core project is as follows
app.UseMvc(routes =>
{
routes.MapRoute(
name: "AllRoutes",
template: "{*url}",
defaults: new
{
controller = "Base"
}
);
my base controller for my .net core project
//[Route("api/[controller]")]
public class BaseController : Controller
{
[HttpGet]
public IActionResult Get()
{
return Ok("get success");
}
// POST api/values
[HttpPost]
public IActionResult Post([FromBody]string value)
{
return Ok("post success");
}
[HttpPut]
public IActionResult Put([FromBody]string value)
{
return Ok("put success");
}
[HttpDelete]
public IActionResult Delete()
{
return Ok("delete success");
}
}
any ideas?
Why do you even want to use MVC, when you have no controllers or routes?
Just use a custom middleware:
// Startup configure
app.Use(async (context, next) =>
{
var service = context.RequestServices.GetRequiredServce<MyService>();
var service.Execute();
async next();
});
Update
Just in case it's not clear, you can inject IHttpContextAccessor in your service, where you can directly access the request stream and do whatever you need to do with it.
public class BaseContoller : Controller {
[HttpGet("/base/get")]
public IActionResult Get() {
return Ok("get success");
}
[HttpPost("/base/post")]
public IActionResult Post() {
return Ok("post success");
}
}
you looking for something like this?
or if you want to route this links you need add something like this
public class BaseController : Controller {
[Route("/get")]
public IActionResult Get() {
return Ok("get success");
}
}
This may be simple and its wierd and I cannot find out the reason why its hapenning.
I am using ASP.NET WEB API 2 Controller: I have a TransactionController, which suddenly stopped working after some modification in one of its action methods. I returned the code back, but its not working anymore.
All the other controllers are working normally. So, I decided two test it by creating two new controllers:
ValueController:
public class ValueController : ApiController
{
public List<string> GetValues()
{
return new List<string>() { "1", "2"};
}
public List<string> GetValues (int ID)
{
return new List<string>() { "1", "2" };
}
public List<string> GetValues(int UserID, DateTime CreateDate)
{
return new List<string>() { "1", "2" };
}
}
TransactionController:
public class TransactionController : ApiController
{
public List<string> GetTransaction(int ID)
{
return new List<string>() { "1", "2" };
}
}
This my webApiConfig
public static void Register(HttpConfiguration config)
{
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
When requesting the item controller by the url:
http://localhost:1607/api/value?ID=1, its hitting the GetValues(int ID) action
and the other actions are working fine.
But, the problem is still with the TransactionController. When requesting it using the url: http://localhost:1607/api/transaction?ID=1. Its not hitting the action.
This the response of the request:
And Its returning back the index view page in the home controller.
Any thoughts why this might happen?
I have the following WebApiConfig.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.EnableSystemDiagnosticsTracing();
// config.MessageHandlers.Add(new TokenValidationHandler());
// config.MessageHandlers.Add(new LoggingHandler());
config.Filters.Add(new ApiCustomExceptionHandler());
}
And I implemented the ExceptionFilterAttribute as follows
public class ApiCustomExceptionHandler : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
var exceptionType = context.Exception.GetType();
if (exceptionType == typeof(UnauthorizedAccessException))
{
context.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
My controller is declared thus:
[ApiCustomExceptionHandler]
public class UserManagementController : ApiController
{
....
}
The problem is OnException never gets invoked, when I throw a UnAuthorizedAccessException. Any idea why this is so?
-Arun
When I had this problem, it turned out actually to be an problem on one action only -- other actions in the controller were fine. The problematic method was returning a generic (in my case,IEnumerable<Dictionary<string, object>>). I fixed this by returning an array instead: Dictionary<string, object>[].
Notice that returning a generic also gives warning CA1006 if you have Static Code Analysis enabled.
I have started a Web API project, and extended it to also be a normal MVC project. By this I mean I have some controllers deriving from ApiController and others from Controller.
Here's my DependencyResolver:
public class StructureMapDependencyResolver :IDependencyResolver
{
public IDependencyScope BeginScope()
{
return this;
}
public StructureMapDependencyResolver(IContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
if (serviceType.IsAbstract || serviceType.IsInterface)
return _container.TryGetInstance(serviceType);
return _container.GetInstance(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.GetAllInstances<object>()
.Where(s => s.GetType() == serviceType);
}
private readonly IContainer _container;
public void Dispose() { }
}
and here's my Global.asax.cs:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ObjectFactory.Initialize(x =>
{
x.For<IDataService>().Use<MockDataService>();
});
ObjectFactory.Configure(x => x.Scan(scan =>
{
scan.AssembliesFromApplicationBaseDirectory();
scan.LookForRegistries();
scan.TheCallingAssembly();
scan.WithDefaultConventions();
}));
var container = ObjectFactory.Container;
GlobalConfiguration.Configuration.DependencyResolver =
new StructureMapDependencyResolver(container);
}
The Web API controllers are working great, but I can't get constructor injection to work in the Controller-derived ones. It's the usual No parameterless constructor defined for this object error message of course.
I'm at a bit of a loss here... this is my first foray into Web API so I'm not sure where I'm going wrong.
You need to call the DependencyResolver.SetResolver to your MVC IOC container. Make sure your container implements MVC's IDependencyResolver as well, otherwise it won't work for MVC.