API controller in MVC App not working - c#

I have created an mvc application with SSO. I have added an Api controller, but whenever i try to get data from it, i get error.
URI= https://localhost:44305/api/graph/get
Error:
Server Error in '/' Application.
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: /api/graph/get
Here is my Route config
public class RouteConfig
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routes.MapRoute(
// name: "Default",
// url: "{controller}/{action}/{id}",
// defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
routes.MapRoute(
name: "Default",
url: "api/{controller}/{action}/{id}",
defaults: new { controller = "Graph", action = "Get", id = UrlParameter.Optional }
);
}
}
This is my web api controller
public JsonResult<List<Claim>> Get()
{
var principal = (User as ClaimsPrincipal);
List<Claim> claimsList = new List<Claim>();
foreach (var claim in principal.Claims)
{
claimsList.Add(claim);
}
return Json<List<Claim>>(claimsList);
}
Not getting any build error. Any help is appreciated

Hy Guys.Thanks for all your help. I have figured out the solution. The answer is that in Global.asax.cs,
GlobalConfiguration.Configure(WebApiConfig.Register)
has to be called before
RouteConfig.RegisterRoutes(RouteTable.Routes).

public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional }
);
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultDataApi",
routeTemplate: "Api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
public class MvcApplication : 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);
FluentValidationModelValidatorProvider.Configure();
}
}

You should have 2 config files:
RoutesConfig.cs and WebApiConfig.cs
RoutesConfig should look like this:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
Log.Instance().Debug("Registering Routes");
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
}
WebApiConfig.cs should look like this:
public static class WebApiConfig
{
public static void Configure(HttpConfiguration config)
{
ConfigureRouting(config);
ConfigureFormatters(config);
}
private static void ConfigureFormatters(HttpConfiguration config)
{
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new NiceEnumConverter());
}
private static void ConfigureRouting(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional, #namespace = "api" });
}
}
Within global.asax.cs you should have something like this:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// Register them in this order
GlobalConfiguration.Configure(WebApiConfig.Configure); //registers WebApi routes
RouteConfig.RegisterRoutes(RouteTable.Routes); //register MVC routes
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Your controller does look a little strange why not let the default serialiser take care for things for you:
public IEnumerable<Claim> Get()
{
var principal = (User as ClaimsPrincipal);
List<Claim> claimsList = new List<Claim>();
foreach (var claim in principal.Claims)
{
claimsList.Add(claim);
}
return claimsList;
}
EDIT: removed redundant code

Assuming the name of your controller is GraphController, I think the url you should be using is /api/graph/get.
If it's named something different, you'll need to adjust the url accordingly.
Also, there's a separate .cs file in MVC projects you should use to manage WebAPI routes - WebApiConfig.cs

Related

ASP.net Web API 2 block route in area on root

I have a route defined in an area, have set the configuration up and routes are firing as expected, however, I can hit the area routes on the root profile as well.
Is there a way to block the root profile from seeing my area routes (defined only in the area only), something like this:
/area/api/awesomeservice -> only this one should be allowed
/api/awesomeservice -> should not be allowed
RouteConfig.cs:
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[] { "TestBed.Controllers" }
);
}
}
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 }
);
}
Service controller under /Areas/Services
ServiceController.cs
namespace TestBed.Areas.Services.Controllers
{
public class HotFuzzController : ApiController
{
[HttpGet]
public string Get()
{
return "Hello World";
}
}
}
Area configuration for Areas/Services
ServicesAreaRegistration.cs
namespace TestBed.Areas.Services
{
public class ServicesAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Services";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.MapHttpRoute(
name: "ServicesApiAction",
routeTemplate: "services/api/{controller}/{action}");
context.Routes.MapHttpRoute(
name: "ServicesApi",
routeTemplate: "services/api/{controller}");
context.MapRoute(
"Services_default",
"Services/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "TestBed.Areas.Services.Controllers" }
);
}
}
}
Global.asax.cs
namespace TestBed
{
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);
}
}
}
The problem comes from the default route that matches the areas controllers. Unfortunately there is no way in the framework (that I know of) to make a route only for controllers that are not in an area.
But you can make a custom RouteContraint and apply your own matching rules. Here is an example of a route constraint that uses reflection to match only controllers of the executing assembly that are in namespaces :
public class NamespaceFilterConstraint : System.Web.Http.Routing.IHttpRouteConstraint
{
private Type[] types;
public string[] AllowedNamespaces { get; }
public NamespaceFilterConstraint(string[] ns)
{
AllowedNamespaces = ns;
types = Assembly.GetExecutingAssembly().GetTypes();
}
public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection)
{
var controllerName = values["controller"] + "Controller";
//This assumes no controllers with the same name in different namespaces
Type controllerType = types.FirstOrDefault(t => t.Name == controllerName);
return AllowedNamespaces.Contains(controllerType.Namespace);
}
}
You can use it in the WebApiConfig :
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: new { controller = new NamespaceFilterConstraint(new string[] { "MyApp.Controllers" }) }
);

MVC5 WebApi2 route not working

I have checked links related to mvc5, webapi2 but not being able to figure out my mistake.
My Problem:
/api/EBanking/CheckLogin is not excuting code of checkLogin method in ebankingcontroller
Links checked:
Custom Routing not working in MVC5
WebAPI2 and MVC5 route config
QueryString with MVC 5 AttributeRouting in Web API 2
App_start Code:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AutoMapperCentralAppConfig.Configure();
}
RouteConfig.cs
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 string UrlPrefixRelative { get { return "~/api"; } }
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ActionBased",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
APi Controller:
[RoutePrefix("api/EBanking")]
public class EBankingController : ApiController
{
public EBankingController()
{
//some other code, it runs
}
[HttpGet, HttpPost]
[Route("CheckLogin")]
public IEnumerable<usr06user_role> CheckLogin(string UserName, string Password)
{
//main code which doesn;t runs
}
public IEnumerable<usr06user_role> GetAll()
{
//test code which runs when we call: /api/ebanking/
}
result screenshot:
In your WebApiConfig.cs add another route for action based routing like this:
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ActionBased",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
This "api/{controller}/{action}/{id}" will allow calls to api/ebanking/checklogin
Alternatively you can even add full route in attribute such as:
[Route("api/EBanking/CheckLogin")]
public IEnumerable<usr06user_role> CheckLogin(string UserName, string Password)
{
//main code which doesn;t runs
}

Unable to hit Web Api in .Net MVC

Hi I am just starting to mess with WebApi to setup a REST api for my angular app.
I simply just added a "Web API 2 Controller with read/write actions"
I then just try to test it by just typing the url in the browser but I get a 404.
Everything is pretty much out of the box.
WebApiConfig.cs looks like
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 }
);
}
}
RouteConfig.cs is
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 }
);
}
}
Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configure(WebApiConfig.Register);
InitializeDatabase("Data Source=.;Initial Catalog=msproto;Integrated Security=True;MultipleActiveResultSets=True;");
}
Is there something I have to add to the web config? If I add a normal controller "MVC 5 Controller with read/write actions" it will hit my breakpoints in the get requests.
Make sure the Web API routes are registered before the MVC routes in your Global.asax.

Use WebApi controller as default instead of MVC vontroller

I have a webapi project and I don't want to return any html or razor views. I want the default controller and action to be an HTTP GET for one of my API controllers. My code is the following:
MVC route config:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteTable.Routes.MapRoute(
"Default",
"{controller}/{id}",
new { controller = "Enpoint", action = "Get", id = UrlParameter.Optional }
);
}
}
WebApi route config:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ApiDefault",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Application_Start:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
Do you know how can I configure the router to redirect to by default:
GET /api/home

Asp.net MVC Web API Call Redirect to Accountcontroller Login

My code is
RouteConfig:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Dashboard", action = "Index", id = UrlParameter.Optional }
);
}
WebAPIConfig:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
}
WebAPI Controller:
public class ServicesController : ApiController
{
public string Get()
{
return "Hello World";
}
}
AccountCtonroller:
public ActionResult Login(string returnUrl)
{
// User Login functionality
ViewBag.ReturnUrl = returnUrl;
return View();
}
Global.asax.cs
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Issue I am facing here is:
1. when i invoke Webapi http://localhost/myapplication/api/services in browser, it redirect to
http://localhost/myapplication/Account/Login?ReturnUrl=%myapplication%2Fapi%2Fservices
Any thoughts on this?
Thanks,
i think your problem is that you dont set action on webapiconfig:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{param}",
defaults: new { param = RouteParameter.Optional }
);
and you need call to controller with action something like:
http://localhost/myapplication/api/services/Get
And add [AllowAnonymous] as #qamar sais

Categories

Resources