asp.net core web api center routing - asp.net-mvc-routing

I have an issue related with asp.net core center routing. I know we could use Attribute Routing, but I did not find anything related with center routing like asp.net web api.
Something like below:
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Could you share me how to achieve above function in asp.net core? If there is no built-in function, could custom routing service achieve this?
Regards,
Edward

center routing is supported for web api, but we need to disable attribute route on web api.
Route:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "api",
template: "api/{controller=Values}/{action=GetAll}/{id?}");
});
Web API controller:
//[Route("api/[controller]")]
//[Authorize]
public class ValuesController : Controller
{
private ApplicationDbContext _db;
public ValuesController(ApplicationDbContext db)
{
_db = db;
}
// GET: api/values
//[HttpGet]
public IEnumerable<string> GetAll()
{
var result = from user in _db.UserInfos
select user.UserName;
return result.ToList();
//return new string[] { "value1", "value2" };
}
// GET api/values/5
//[HttpGet("{id}")]
public string GetById(int id)
{
var result = from user in _db.UserInfos
select user.UserName;
return result.FirstOrDefault();
//return User.Identity.IsAuthenticated.ToString(); //"value";
}
}
This could be requested by http://localhost:44888/api/values/getbyid/123

You can configure the routes as options to MVC middleware. Add the routes to the configure method in your startup class
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseMvc(routes =>
{
routes.MapRoute("blog", "api/{*article}",
defaults: new { controller = "Blog", action = "Article" });
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Note that in ASP.NET, the controller are same for both MVC and API. Its an unified model.

Related

How to override route in a plugin nopcommerce

I've a route like Admin/Vendor in my MVC application . Without changing this route I need to point this same route to another method say CustomAdmin/CustomVendor.
I tried attribute routing but no luck . Is there any way to do this. My current code is given below
Original Method:
public class AdminController
{
public ActionResult Vendor()
{
return View();
}
}
Custom Method:
public class CustomAdminController
{
[Route("Admin/Vendor")]
public ActionResult CustomVendor()
{
return View();
}
}
As you're developing a plugin. You have to add your custom route to the RouteProvider.
In default nopCommerce AdminController and Vendor doesn't exists, so I assume that you're trying to override vendor list method of admin.
Which looks like:
public partial class RouteProvider : IRouteProvider
{
public void RegisterRoutes(RouteCollection routes)
{
var route = routes.MapRoute("Plugin.GroupName.PluginName.CustomVendor",
"Admin/Vendor/List",
new { controller = "CustomAdminController", action = "CustomVendor", orderIds = UrlParameter.Optional, area = "Admin" },
new[] { "Nop.Plugin.GroupName.PluginName.Controllers" });
route.DataTokens.Add("area", "admin");
routes.Remove(route);
routes.Insert(0, route);
}
public int Priority
{
get
{
return 100; // route priority
}
}
}
Side Note: GroupName and PluginName should be your plugin group name and plugin name.
Hope this helps !
On your plugin which class implements the interface IRouteProvider, you can easily override the route there.
Likewise I have a class named RouteProvider in my plugin, So I have Implemented the abstract function RegisterRoutes and simply it can be overrided by
routes.MapRoute("Plugin.Promotion.Combo.SaveGeneralSettings",
"Admin/Vendor",
new { controller = "CustomAdmin", action = "CustomVendor", },
new[] { "Nop.Plugin.Promotion.Combo.Controllers" }
);
Here Plugin.Promotion.Combo must be replaced by your plugin directory.And using SaveGeneralSettings or any things you want to use that will be your route url

Can't get .net core MVC to redirect 401 to /Account/Login

When I request a controller action that is [Authorize] decorated instead of being redirected to the login page I receive a 401 error.
This is a .net core mvc app using the identity template running on IIS express.
When i run the app from program.cs the redirect to login works fine.
I've added explicit directions to for the cookie authentication to use the /Account/Login redirect both for configuration and services section, as well as configuring Identity to perform this redirect.
I can't get it to work. Below is my StartUp class, what should I change to make it work in IIS express?:
public class Startup
{
private MapperConfiguration _mapperConfiguration { get; set; }
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
if (env.IsDevelopment())
{
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
builder.AddUserSecrets();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
_mapperConfiguration = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new AutoMapperProfileConfiguration());
});
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>(
option => {
option.Cookies.ApplicationCookie.LoginPath = "/Account/Login";
option.Cookies.ApplicationCookie.AutomaticChallenge = true;
option.Cookies.ApplicationCookie.AutomaticAuthenticate = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddDataProtection();
services.AddMvc();
services.AddSignalR();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.Configure<IISOptions>(options => options.AutomaticAuthentication = true);
services.AddSingleton<IMapper>(sp => _mapperConfiguration.CreateMapper());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ApplicationDbContext context, RoleManager<IdentityRole> roleManager)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseStaticFiles();
app.UseIdentity();
// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
//app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "MyCookies",
SlidingExpiration = true,
AutomaticAuthenticate = true,
AutomaticChallenge = true,
LoginPath = new PathString("/Account/Login")
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "index",
template: "{controller=Home}/{id?}",
defaults: new { action = "Index" });
});
app.UseSignalR();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
MyDbInit.Init(context, roleManager);
}
}
I had this same problem all night and could not find a solution to it. Running the site directly from Kestrel redirected fine, but through IIS or IIS Express it simply would not redirect - it would go to a white page.
After posting to the Identity Git about it, I realized that my template was set up to run under 1.0.1 of the framework, not 1.1.0. I updated it to use 1.1.0 and updated all the Nuget packages to 1.1.0 and now it is redirecting in IIS and IIS Express properly.
I'm not sure if the package updates "fixed" something that was screwy, or if this was simply a problem with 1.0.1 that was fixed in 1.1.0.
https://blogs.msdn.microsoft.com/webdev/2016/11/16/announcing-asp-net-core-1-1/
Identity adds cookie authentication automatically. You're adding it a second time in Configure.
When you add the second instance you're setting both the automatic properties, so now two middlewares are trying to do the redirection, and that behaviour is "undefined" (where undefined == "Going to seriously mess things up").
This line inside Configure method in Startup class, resolve me problem:
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseAuthentication(); // <= This line
app.UseMvc(routes =>
{
...
});
}
}

Enable hyphens in URLs for MVC 5 website

My project is multilingual and also has routing, but I need to allow hyphens in the URLs, such as: example.com/en/our-team.
In this website (http://www.bousie.co.uk/blog/allow-dashes-within-urls-using-asp-net-mvc4/) I found a solution to this, adding the following code in Global.asax :
public class HyphenatedRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.RouteData.Values["controller"] =
requestContext.RouteData.Values["controller"].ToString().Replace("-", "_");
requestContext.RouteData.Values["action"] =
requestContext.RouteData.Values["action"].ToString().Replace("-", "_");
return base.GetHttpHandler(requestContext);
}
}
And on RouteConfig.cs, replace this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index",
id = UrlParameter.Optional }
);
With this:
routes.Add(
new Route("{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller = "Home", action = "Index", id = "" }),
new HyphenatedRouteHandler())
);
The problem is that i don't know how to do it in my code:
using System.Web.Mvc;
using System.Web.Routing;
namespace theme_mvc
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapLocalizeRoute("Default",
url: "{culture}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { culture = "[a-zA-Z]{1}[a-zA-Z]{1}" });
routes.MapRouteToLocalizeRedirect("RedirectToLocalize",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
}
}
How could i adapt my code to support hyphens (-) in the URL?
The link you have posted to uses the wrong approach. Routing is a 2-way mapping, but if you only customize the MvcRouteHandler, you are only taking into account the incoming routes.
This issue comes up so often that someone has created a hyphenated lowercase route project on GitHub, which would do what you want except you need to also combine it with the route that is being called by your MapLocalizeRoute extension method.
But since you have not posted the code for MapLocalizeRoute or MapRouteToLocalizeRedirect I can't tell you how that is done.

How to set Area view as home page in ASP.NET MVC?

How to setup route for a view to be as home page of a domain in ASP.NET MVC application which contains Areas. I need a view of a particular area to be home page. How could this be done?
I tried using the following code without any success.
public static void RegisterRoutes(RouteCollection routes) {
routes.MapRoute(
name: "Home",
url: "",
defaults: new { controller = "Home", action = "Index" },
namespaces: new string[] { "WebApp.Areas.UI.Controllers" }
);
}
In the Area folder there is a file by name AreaNameAreaRegistration deriving from AreaRegistration, it has a function RegisterArea which sets up the route.
Default route in an Area is AreaName/{controller}/{action}/{id}. Modifying this can set an area as default area. For example I set the default route as {controller}/{action} for my requirement.
public class UIAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "UI";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"UI_default",
"{controller}/{action}/{id}", //******
new {controller = "Home", action = "Index", id = UrlParameter.Optional}
);
}
}

How should I work around an ASP.Net MVC Route mapping conflict?

I have two routes mapped in my MVC application:
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Project",
"{controller}/{projectid}/{action}/{id}",
new { controller = "Project", action = "Index", id = "" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
For the most part, these pose no problems, but I do strike trouble when trying to call the /Account/LogOn view. My ActionLink syntax looks like this (I've tried a couple of variations including null route values and such):
<%= Html.ActionLink("Log On", "LogOn", "Account") %>
Browsing to this view raises a 404 error ("The resource cannot be found"). Ideally I'd like to avoid a huge amount of rework, so what would be the best way to avoid these clashes?
Have you tried this variation with the literal for the controller?
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Project",
"Project/{projectid}/{action}/{id}",
new { controller = "Project", action = "Index", id = "" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
This would catch: http://localhost/Project/12 and http://localhost/Project/12/Edit and http://localhost/Project/2/View/2
But it would pass http://localhost/Account/LogOn to the second rounte. Yes?