Modifying the routing asp mvc - c#

In my ASP MVC application, I need to show the URL path like this:
domain.com/viewName
I have the route config in the follow way:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.RouteExistingFiles = false;
routes.IgnoreRoute("{*allfiles}", new { allfiles = #".*\.(css|js|gif|jpg|png)" });
routes.MapRoute(
"Theme",
"theme/{theme}/{page}",
new { controller = "Theme", action = "Index", page = UrlParameter.Optional },
new[] { "Tenant.Controllers" }
);
routes.MapRoute(
"ThemeSlider",
"theme/slider/{id}",
new { controller = "Theme", action = "Slider" },
new[] { "Tenant.Controllers" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "Tenant.Controllers" }
);
routes.MapRoute(
"Default_tenant",
"{page}",
new { controller = "Home", action = "Index", page = UrlParameter.Optional },
new[] { "Tenant.Controllers" }
);
routes.MapMvcAttributeRoutes();
}
But it does not works, I have to specify the page parameter in the follow way: domain.com/?page=viewName. How should be the route config that leaves the follow routes:
domain.com.co/controller/action/
domain.com.co/view
Any sugestion ?? Thanks in advance

You mean to get rid of the controller? This sort of thing will work, but beware of conflicts between routes in different controllers:
routes.MapRoute(
name: "HomeRoute",
url: "{action}",
defaults: new {controller = "Home", action = "Index"},
constraints: new { homeControllerConstraint = new HomeControllerConstraint() }
);
Now every action in the home controller maps to Domain.com/Action instead of Domain.com/Home/Action.
Here is some reflective code to efficiently work out whether a route is in the home controller, for instance.
internal class HomeControllerConstraint : IRouteConstraint
{
private static readonly Lazy<HashSet<string>> homeMethods = new Lazy<HashSet<string>>(CreateHomeMethods);
private static HashSet<string> CreateHomeMethods()
{
return typeof(HomeController).GetMethods().Select(e => e.Name.ToLower()).ToSet();
}
public static bool Exists(string name)
{
return homeMethods.Value.Contains(name.Trim().ToLower());
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
return homeMethods.Value.Contains(values["action"].ToString().ToLower());
}
}

Related

ASP.net customized routing with Action/Id

I've been trying to change the routing for my website for the past few hours and I just can't find out what ASP.net wants from me!
This is my default routing:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{Id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, }
);
It successfully brings up Home/Index whenever I go to these URLs:
/
/Home
/Home/Index
However, I have an action called "K" like below which receives a parameter "name":
public ActionResult K(string name)
I want to define a route that will redirect me to /Home/K/{name} with this template:
website.com/K/{name}
I tried this route below but It doesn't work:
routes.MapRoute(
"OnlyK",
"K/{id}",
new { controller = "Home", action = "K", id = UrlParameter.Optional }
);
Also even without this route config, if I go to website.com/Home/K/something It will not recognize "something" as id (controller parameter == null)!
What am I doing wrong?
The url website.com/Home/K/something results in a null value for argument name in the K action method ActionResult K(string name) because the argument names don't match.
This method is being served via the the route Default, which
declares a parameter with name id (via {controller}/{action}/{id}), whereas action method K has an argument named name.
You can solve this by overruling the argument name on the action method, via the BindAttribute so that both match.
ActionResult K([Bind(Prefix ="id")] string name)
To do a redirect from website.com/K/{name} to website.com/Home/K/{name} you can set up a custom IRouteHandler that takes care of this redirect.
Register a route that handles any request that match route K/{id} and redirect these to a route with a wellknown name (here: K).
Because of the argument name mismatch discussed about we'll use {id} instead of {name} in our routes.
routes.Add(new Route("K/{id}", new RedirectRouteHandler("K")));
Define this route K as below.
routes.MapRoute(
name: "K",
url: "Home/K/{id}",
defaults: new { controller = "Home", action = "K", id = UrlParameter.Optional }
);
The RouteHandler and RedirectHandler doing the redirect.
The HttpResponse class has a RedirectToRoute method that can deal with route names and route values, without having to construct urls ourselves.
class RedirectRouteHandler : IRouteHandler
{
private readonly string _routeName;
public RedirectRouteHandler(string routeName)
{
_routeName = routeName;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new RedirectHandler(this._routeName, requestContext.RouteData.Values);
}
}
class RedirectHandler : IHttpHandler
{
private readonly string _routeName;
private readonly RouteValueDictionary _routeValues;
public RedirectHandler(string routeName, RouteValueDictionary routeValues)
{
this._routeName = routeName;
this._routeValues = routeValues;
}
public bool IsReusable { return false; }
public void ProcessRequest(HttpContext context)
{
context.Response.RedirectToRoute(this._routeName, this._routeValues);
}
}
Note that the order of the registered routes matters; RegisterRoutes looks like.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new Route("K/{id}", new RedirectRouteHandler("K")));
routes.MapRoute(
name: "K",
url: "Home/K/{id}",
defaults: new { controller = "Home", action = "K", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}

Controller Redirect not executing method

Following all suggested remedies, still my method is not getting called.
The method being called is in the same controller. TEST can be called either by itself through a link on a separate page, or when a user selects a saved "TEST" view that they wish to load again. In this case, the below LoadUserSelectedTransaction is called.
I've tried specifying the controller to use with no luck, hard coding requestType, [HTTPPOST] attribute, removing FormMethod.Post from the view
View is as follows:
using (Html.BeginForm("LoadUserSelectedTransaction", "TransactionList", FormMethod.Post))
Controller is as follows
public class TransactionListController : Controller
{
public static bool userLoaded = false;
public static string userFriendlyName;
public static string transaction;
public static string requestType;
//[HttpPost]
public ActionResult LoadUserSelectedTransaction(FormCollection formdata)
{
userLoaded = true;
userFriendlyName = formdata["UserLoadedTransaction"];
var model = new MyTransactionsDBHandle();
transaction = model.ReturnUserLoadedTransaction(userFriendlyName, User.Identity.Name);
var myTransaction = new MyTransactionsModel();
requestType = myTransaction.ReturnRequestType(transaction);
if (requestType == "")
{
requestType = formdata["CurrentTransactionPage"];
}
// need to check for duplicate transactions types, such as CC_SALE also being a POS Surcharge transaction
// CC_SALE has EMV, ship to, bill to etc, POS Surcharge does not
// CC_VOID with and without card - With card will have NGT_TRACKDATA tag
// DB_SALE with and without cashback - Cashback will have NGT_DC_CASH_BACK_AMOUNT tag
if (requestType == "DB_SALE")
{
if (transaction.Contains("NGT_DC_CASH_BACK_AMOUNT"))
return RedirectToAction("DB_Sale_With_Cash_Back");
return RedirectToAction("DB_Sale_No_Cash_Back");
}
else if (requestType == "CC_SALE")
{
if (transaction.Contains("NGT_EMV_DATA"))
return RedirectToAction(requestType);
return RedirectToAction("CC_POS_Surcharge");
}
else if (requestType == "CC_VOID")
{
if (transaction.Contains("NGT_TRACKDATA"))
return RedirectToAction(requestType);
return RedirectToAction("CC_Void_No_Card");
}
else
return RedirectToAction(requestType);
}
}
Method being called:
public ActionResult TEST(FormCollection formdata)
{
ViewModel model = new ViewModel();
if (userLoaded) // static in same controller
{
userLoaded = false;
if (requestType == "My Transactions")
{
var currentTransactionPage = formdata["CurrentTransactionPage"];
return RedirectToAction(currentTransactionPage);
}
model.myTransactions.ParseUserTransactionString(transaction, model);
}
return View(model);
}
Any suggestions are greatly appreciated, thanks in advance!
RouteConfig.cs
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 = "User", action = "Login", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "ClientTablePages",
url: "{controller}/{action}/{pageNumber}",
defaults: new { controller = "Client", action = "Index", page = UrlParameter.Optional }
);
routes.MapRoute(
name: "DivisionTablePages",
url: "{controller}/{action}/{pageNumber}",
defaults: new { controller = "Division", action = "Index", page = UrlParameter.Optional }
);
routes.MapRoute(
name: "MerchantTablePages",
url: "{controller}/{action}/{pageNumber}",
defaults: new { controller = "Merchant", action = "Index", page = UrlParameter.Optional }
);
routes.MapRoute(
name: "TerminalTablePages",
url: "{controller}/{action}/{pageNumber}",
defaults: new { controller = "Terminal", action = "Index", page = UrlParameter.Optional }
);
routes.MapRoute(
name: "ResetPassword",
url: "{controller}/{action}/{id}",
defaults: new { Controller = "User", action = "UserResetPassword", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "MyTransactions",
url: "{controller}/{action}/{pageNumber}",
defaults: new { Controller = "MyTransactions", action = "MyProfile", page = UrlParameter.Optional }
);
}
}
RedirectToAction returns a 302 redirect to the browser which is always a GET request.
In comparison Server.TransferRequest(url, true) performs a server redirect preserving the postBack values using a POST request.
P.S. Browser won't be aware of this redirect hence the browser url will not reflect the new address

How to await a service call in routes.MapRoute in MVC5

I am doing a massive overhaul on a custom CMS that I am writing in MVC5. This custom CMS has "pages" that have "urls" stored in a database. For instance if a user requested /stackoverflow in the browser and there was a page in the database with /stackoverflow listed as the url, then I am serving the database content at the specificed CoreCms/Index Controller and view with the database content as a model property. The idea is that I can use this single controller/view to serve up any page in the database.
The rewrite that I am working uses dependency injection and async calls only in the service layer. It seems that I am having a bit of trouble with the RouteConfig RegisterRoutes static method.
Here's some code...
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("FileBrowser/{pathInfo}");
routes.MapRoute(
name: "CmsRoutes",
url: "{*permalink}",
defaults: new { controller = "CmsCorePage", action = "Index" },
constraints: new { url = new CmsCoreRouting() }
);
routes.MapRoute(
name: "ArticlesCategoryRoute",
url: "Articles/{categoryURL}",
defaults: new { controller = "CmsCoreArticles", action = "Index", categoryURL = UrlParameter.Optional }
);
routes.MapRoute(
name: "ArticlesPostsRoute",
url: "Articles/{categoryURL}/{postURL}",
defaults: new { controller = "CmsCoreArticles", action = "ArticlePost", categoryURL = UrlParameter.Optional, postURL = UrlParameter.Optional }
);
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Note that I am rewriting old code and the constraints: new { url = new CmsCoreRouting() } is code that I intend on altering here I believe.
For reference, here is the CmsCoreRouting class...
public class CmsCoreRouting : IRouteConstraint
{
private ICoreCmsServices _coreSvc;
public CmsCoreRouting()
{
}
public CmsCoreRouting(ICoreCmsServices coreSvc)
{
_coreSvc = coreSvc;
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (httpContext?.Request?.FilePath == null) { return false; }
string myURL = httpContext.Request.FilePath;
if (myURL.StartsWith("/"))
{
myURL = myURL.Substring(1, myURL.Length - 1);
}
myURL = myURL.ToLower();
var siteId = CoreCms.Core.Settings.CoreCmsSettings.SiteId;
var cmsPage = AsyncUtility.RunSync(() => _coreSvc.PageService.FindBySiteAndUrlAsync(siteId, myURL));
if (cmsPage != null)
{
return true;
}
var cmsArticle = AsyncUtility.RunSync(() => _coreSvc.ArticleService.FindCategoryBySiteAndUrlAsync(siteId, myURL));
if (cmsArticle != null)
{
return true;
}
return false;
}
}
Problem: When MVC starts, it calls the parameterless constructor on CmsCoreRouting (because I told it to in url = new CmsCoreRouting()) but I am not sure how to both use AutoFac's DI so that I don't have to pass around my own instances of the service and repository and DbContext on this RegisterRoutes function.
Any help on this would be great. I would like to do this "right".
Just ask the resolver (AutoFac) to create it for you:
routes.MapRoute(
name: "CmsRoutes",
url: "{*permalink}",
defaults: new { controller = "CmsCorePage", action = "Index" },
constraints: new { url = DependencyResolver.Current.GetService<CmsCoreRouting>() }
);

Multiples types were found home controller

I need do put a new home in new area but im have a error:
Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
my new area
Areas/Administrativo/Controllers/HomeController
Areas/Administrativo/Views/Home
my AdministrativoAreaRegistration
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Administrativo_default",
"Administrativo/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
in Global i have
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "Preparacao.Gerenciar.Web.Controllers" } // Parameter defaults
);
}
You should specify the namespace constraint in your area route registration (check if the namespace is correct):
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Administrativo_default",
"Administrativo/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "Preparacao.Gerenciar.Web.Areas.Administrativo.Controllers" }
);
}
the same way you did with your main route registrations:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new[] { "Preparacao.Gerenciar.Web.Controllers" }
);
}

QueryStrings.AllKeys != RawUrl?

Request ["fileName"] return null?? Why?
Full image: http://i.stack.imgur.com/U1MzX.jpg
Controller:
Full image: http://i.stack.imgur.com/DCQNG.jpg
Route
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"AdminLogin",
"Admin/",
new { controller = "Account", action = "Login" }
);
//NossaIgreja/{nomePastor}
routes.MapRoute(
"Pastor", // Route name
"Pastor/{id}", // URL with parameters
new { controller = "NossaIgreja", action = "Pastor" } // Parameter defaults
);
routes.MapRoute(
"Download", // Route name
"Downloads/Boletim/{year}/{week}", // URL with parameters
new { controller = "Downloads", action = "DownloadBoletim" }, // Parameter defaults
new { year = #"\d+", week = #"\d+" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
, new string[] { "SextaIgreja.Web.Controllers" }
);
}
Area registration
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Admin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new string[] { "SextaIgreja.Web.Areas.Admin.Controllers" }
);
}
}
Your controller action should take "fileName" parameter, instead of doing a Request["fileName"]. As long as your query string parameter matches the name of the parameter in your controller mvc should pass it in automatically.
If Remover is an MVC action than I cannot see the parameter in Remover Action called fileName
It means when call Remover action the fileName in your querystring is not getting automatic model binding

Categories