What is the difference between AttributeRoutingConfig and RouteConfig in MVC5? - c#

To understand the code behind the AttributeRoutingConfig I'm trying to recreate it using RouteConfig
AttributeRoutingConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using AttributeRouting.Web.Mvc;
[assembly: WebActivator.PreApplicationStartMethod(typeof(SimplestAuth.AttributeRoutingConfig), "Start")]
namespace xyz
{
public static class AttributeRoutingConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapAttributeRoutes();
}
public static void Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
}
RoutingConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace xyz
{
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 = "login", id = UrlParameter.Optional }
);
}
}
}
I'm looking for information to understand the differences and similarities between the two techniques. Thank you.

They both do essentially the same thing:
They register your routes to the RouteTable.
The first code sample you have above utilizes AttributeRouting so it does an assembly scan.
The second code sample you have utilizes the RouteTable directly, so it is a much more manual looking process.
Hope that helps.

Related

API Controller added to ASP.NET MVC web application doesn't seem to work

I have an ASP.NET MVC web application that I'm trying to add an API Controller to so that I can make front-end AJAX calls with jQuery.
I have seen several posts on stack overflow about how to add an API controller successfully to an MVC project and although I followed the instructions and have tried to avoid the common issues (I have added the required API dependencies and made sure that my API routes are being initialized before the MVC routes in my global.asax.cs)
My API Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace mywebsite.net.Controllers
{
public class WebAPIController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
}
My WebApi.config:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace mywebsite.net
{
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 }
);
}
}
}
My Global.asax.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using System.Web.Http;
namespace mywebsite.net
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
When I try to send a GET request that I think should return information (in this case something like localhost:12345/api/WebAPI), nothing happens. The browser/http client just gets stuck loading.
Try putting a [HttpGet] above public IEnumerable<string> Get()
It turns out the API Controller was being served on a different port. -.-

Adding WebForm to MVC application to work with extension less webform page

I have an MVC application in which I have to integrated few webforms pages.
I simply added a webform "WebForm.aspx" to root and it worked without any issue when I accessed webform with file exetension http://localhost:54363/WebForm.aspx but same files doesnt work when I try to access it without file extension .aspx
http://localhost:54363/WebForm for this is get 404 error.
For this to work I made changes to Global.asax file as per the this article but it didnt work
Below is the code of Global.asax file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace ProjectNameSpace
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.RouteExistingFiles = true;
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("Content/{*pathInfo}");
routes.IgnoreRoute("Scripts/{*pathInfo}");
routes.IgnoreRoute("{WebPage}.aspx/{*pathInfo}");
routes.IgnoreRoute("{resource}.ashx/{*pathInfo}");
//routes.MapRoute(
// "Default", // Route name
// "{controller}/{action}/{id}", // URL with parameters
// new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
//);
routes.MapPageRoute("home", "WebForm/", "~/WebForm.aspx", false,
new RouteValueDictionary {
{ "path", "page-not-found" },{ "pagename", "page-not-found" }
});
}
}
}
Am I going something wrong in the above code or what is the correct way of setting route for WebForm.aspx file.
UPDATE:
I managed to solve this by adding webform route code also in RouteConfig.cs file also
using AlhabtoorTennisAcademy.CustomFilters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace ProjectNameSpace
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// webforms page route
//Custom route code for webform
routes.MapPageRoute("home", "WebForm", "~/WebForm.aspx", false,
new RouteValueDictionary {
{ "path", "page-not-found" },{ "pagename", "page-not-found" }
});
}
}
........
From what I see on the example above, you're adding MapPageRoute after the default MVC routing with MapRoute, hence the order of MapPageRoute is processed after MapRoute, which is wrong because routes are processed from top-most to bottom-most order (most-specific to least-specific).
In order to route webforms pages, the MapPageRoute must precede MapRoute on the top order:
public static void RegisterRoutes(RouteCollection routes)
{
routes.RouteExistingFiles = true;
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("Content/{*pathInfo}");
routes.IgnoreRoute("Scripts/{*pathInfo}");
routes.IgnoreRoute("{resource}.ashx/{*pathInfo}");
// webforms page route
routes.MapPageRoute("home", "WebForm", "~/WebForm.aspx", false,
new RouteValueDictionary {
{ "path", "page-not-found" },{ "pagename", "page-not-found" }
});
// default MVC route
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
Additional note:
You can use placeholder for page names to map all webforms pages in a single MapPageRoute definition:
routes.MapPageRoute("home", "{WebPage}", "~/{WebPage}.aspx");
Related issue:
URL Routing C# mvc and Web Forms

The resource cannot be found when invoke ApiController method

When i try to invoke api controller the getting 404. But when i try to invoke Controller method its working fine. Please help and let me know if any information is required.
TPServicesAPIController.cs:-
using AgentVartualOffice.Models.LogIn;
using System.Web.Mvc;
using AgentVartualOffice.Models;
using Newtonsoft.Json;
using System.Text;
namespace AgentVartualOffice.Controllers.TPServices
{
public class TPServicesAPIController : ApiController
{
public string Myauth()
{
return "True";
}
}
}
Global.asax.cs:-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Http;
namespace AgentVartualOffice
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalFilters.Filters.Add(new HandleErrorAttribute());
}
}
}
Invoke url:
http://localhost:61868/TPServicesAPI/Myauth
Chances are your are calling the wrong URL.
The default Web API convention-based routes are usually prefixed with api
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}", //<<--- default web API route template
defaults: new { id = RouteParameter.Optional }
);
}
}
and also do not use action names unless the route template has been changed.
routeTemplate: "api/{controller}/{action}/{id}"
So I suggest you check your API config and update the URL being called accordingly.
For example, by calling: api/TPServicesAPI/Myaut

Attribute Routing: "Not a valid ODataPath Template"

Ive been struggling with this all day and i think ive reached the end of all the answers ive seen on this. Maybe im special, or maybe im doing something stupid.
I recently upgraded from V3 to V4 (i think). Im using the System.Web.OData namespace which should be fine.
Here is my WebAPIConfig
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using System.Web.OData.Routing;
using System.Web.OData.Routing.Conventions;
using GizmoAPI.Models;
namespace GizmoAPI
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Counterparty>("Counterparties");
config.Select().Expand().Filter().OrderBy().MaxTop(null).Count();
config.EnableDependencyInjection();
config.MapHttpAttributeRoutes();
config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
config.AddODataQueryFilter();
var cors = new System.Web.Http.Cors.EnableCorsAttribute("http://localhost:56248", "*", "*");
config.EnableCors( cors);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));
config.EnableSystemDiagnosticsTracing();
}
}
}
and here is a basic controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using System.Web.OData;
using System.Web.OData.Routing;
using GizmoAPI.Models;
namespace GizmoAPI.Controllers
{
public class CounterpartiesController : ODataController
{
private GizmoEntities db = new GizmoEntities();
// GET odata/Counterparties
[EnableQuery]
public IQueryable<Counterparty> GetCounterparties()
{
return db.Counterparties;
}
// GET odata/Counterparties(5)
[EnableQuery]
[ODataRoute("{key}")]
public SingleResult<Counterparty> GetCounterparty([FromODataUri] int key)
{
return SingleResult.Create(db.Counterparties.Where(counterparty => counterparty.CounterpartyID == key));
}
Then im trying to call the URL as http://localhost:60965/odata/Counterparties/101
or
http://localhost:60965/odata/101
or really anything at this point. I feel like there is some sort of configuration that im missing to activate it. I get the error "The path template '{key}' on the action 'GetCounterparty' in controller 'Counterparties' is not a valid OData path template. Resource not found for the segment '{key}'."
Did you try renaming your method to GetCounterParties([FromODataUri] int key)
and removing the OdataRoute Attribute?
This is not a 100% fix to my problem since i added odata as a tag.
Comparing the ODataController with the ApiController (WebAPI2.2), i couldnt find any reason not to switch to the latter.
So i changed my controller to inherit APIController, and switched all references of odata to the WebAPI version. In fact, the code above is almost identical with the exception of the aforementioned controller and the ODataRoute now becoming simply "Route". The code compiles completely fine and is far more manageable. I can even use the odata filters if the return type of my action is iqueryable.

Breeze WebAPI - Multiple actions were found that match the request

I am using the John Papa Single Page Application source code to create my own App and I am running into some problems when using the Breeze Web API. I have my own breeze controller and as soon as I add a second HttpGET method I get the error "Multiple actions were found that match the request".
It is Weird because in his code he adds multiple GETs and his code works but I think I am missing something.
Breeze Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Breeze.WebApi;
using AgencyUpdate.Models;
namespace AgencyUpdate.Controllers
{
[BreezeController]
public class BreezeController : ApiController
{
readonly EFContextProvider<AgencyDbContext> _ContextProvider =
new EFContextProvider<AgencyDbContext>();
public string MetaData()
{
return _ContextProvider.Metadata();
}
[HttpGet]
public IQueryable<api_Agency> GetAgency()
{
return _ContextProvider.Context.api_Agency;
}
[HttpGet]
public IQueryable<api_AgencyOffice> GetOffice()
{
return _ContextProvider.Context.api_AgencyOffice;
}
}
}
I use this URL to request data:
**http://localhost:13762/api/breeze/GetAgency**
Also I have found this .CS file for routing but I don't know if I have to make changes to it.
BreezeWebApiConfig
using System.Web.Http;
[assembly: WebActivator.PreApplicationStartMethod(
typeof(AgencyUpdate.App_Start.BreezeWebApiConfig), "RegisterBreezePreStart")]
namespace AgencyUpdate.App_Start {
///<summary>
/// Inserts the Breeze Web API controller route at the front of all Web API routes
///</summary>
///<remarks>
/// This class is discovered and run during startup; see
/// http://blogs.msdn.com/b/davidebb/archive/2010/10/11/light-up-your-nupacks-with-startup-code-and-webactivator.aspx
///</remarks>
public static class BreezeWebApiConfig {
public static void RegisterBreezePreStart() {
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "BreezeApi",
routeTemplate: "breeze/{controller}/{action}"
);
}
}
}
Does anyone know what the problem is?
I feel a bit stupid the URL I need to use is breeze/breeze/MethodName.
John's code doesn't use breeze twice in the URL hence the confusion
Papa's course has the single-page-apps-jumpstart.zip file with project source code by chapters. The right version the BreezeWebApiConfig.cs content is as such:
public static class BreezeWebApiConfig {
public static void RegisterBreezePreStart() {
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "BreezeApi",
routeTemplate: "api/{controller}/{action}"
);
}
}
}
Notice the string routeTemplate: "api/{controller}/{action}"

Categories

Resources