After reading this : .NET MVC-4 routing with custom slugs
I was able to implement the solution into my project :
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
).RouteHandler = new SlugRouteHandler(); ;
and made a little change on the SlugRouteHandler class :
public class SlugRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var url = requestContext.HttpContext.Request.Path.TrimStart('/');
if (!string.IsNullOrEmpty(url))
{
if (url.Contains("_escaped_fragment_"))
requestContext.HttpContext.Response.StatusCode = 401;
else
requestContext.HttpContext.Response.StatusCode = 404;
FillRequest("Error","Index", requestContext);
}
return base.GetHttpHandler(requestContext);
}
private static void FillRequest(string controller, string action, RequestContext requestContext)
{
if (requestContext == null)
{
throw new ArgumentNullException("requestContext");
}
requestContext.RouteData.Values["controller"] = controller;
requestContext.RouteData.Values["action"] = action;
}
}
This is the result on my local host, perfect :
but after publishing the project to the host, it doesn't work as I expected :
Is there any chance this is because of the server's configurations?
Related
I have to port over the following ASP.NET MVC code to .NET Core and I'm stuck on how to do this.
This is my old ASP.NET MVC code:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Cultural",
url: "{culture}/{controller}/{action}",
defaults: new { controller = "Home", action = "Index", culture = AppGlobal.DefaultLocale }).RouteHandler = new Routers.CulturalRouteHandler();
}
}
public class CulturalRouteHandler: MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
{
var lang = requestContext.RouteData.Values["culture"].ToString();
var ci = new CultureInfo(lang);
// Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
Thread.CurrentThread.CurrentUICulture = ci;
return base.GetHttpHandler(requestContext);
}
}
I converted the routehandler to the following in .NET Core:
public class CulturalRouteHandler : IRouter
{
private readonly IRouter _defaultRouter;
public CulturalRouteHandler(IRouter defaultRouter)
{
_defaultRouter = defaultRouter;
}
public async Task RouteAsync(RouteContext context)
{
var lang = context.RouteData.Values["culture"].ToString();
var ci = new CultureInfo(lang);
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
CultureInfo.CurrentUICulture = ci;
await _defaultRouter.RouteAsync(context);
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return _defaultRouter.GetVirtualPath(context);
}
}
I'm stuck trying to hook into the route handler for the specific route now.
How would I go about hooking the IRouter into my code for program. cs below:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapControllerRoute(
name: "Cultural",
pattern: "{culture}/{controller}/{action}",
defaults: new { controller = "Home", action = "Index", culture = AppGlobal.DefaultLocale };
You change your RouteHandler implementation
public class MyRequestHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MyHttpHandler(this, requestContext);
}
}
I am trying to create constraint for route.Based on the access info retrieved from Db,i will choose which route to choose.
I have created controller inheriting IRouteConstraint and calling repository,but Unable to get result from httpclient call.
Code snippet of my routeConfig
routes.MapRoute(
name: "Home",
url: "{*routelink}",
defaults: new { controller = "Home", action = "Index" },
constraints: new { routelink = new UserAccessController("Home") }
);
routes.MapRoute(
name: "Reports",
url: "{*routelink}",
defaults: new { controller = "Reports", action = "Index" },
constraints: new { routelink = new UserAccessController("Reports") }
);
Code snippet of Constarint
public class UserAccessController : IRouteConstraint
{
// GET: UserAccess
private readonly string _controller;
public UserAccessController(string Controller)
{
_controller = Controller;
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
bool _authorized = false;
var userAccessDetails = GetUserRoleDetails();
switch (_controller)
{
case "Home":
{
_authorized = Convert.ToBoolean(userAccessDetails.CanAccessHome);
return _authorized;
}
case "Reports":
{
_authorized = Convert.ToBoolean(userAccessDetails.Result.CanAccessReports);
return _authorized;
}
}
return _authorized;
}
public async Task<UserRole> GetUserRoleDetails()
{
IRepository _repository = new Repository();
var userRoleDetails = new UserRole();
var currentUser = await _repository.GetCurrentUser(Path.GetFileName(HttpContext.Current.User.Identity.Name.ToUpper()));
if (currentUser != null)
{
var roles = await _repository.GetUserRoles();
userRoleDetails = roles.Where(r => r.RoleId == currentUser.RoleId).FirstOrDefault();
}
return userRoleDetails;
}
}
the repository is calling httpwrapper class to get result from httpclient.
public static async Task<IEnumerable<T>> GetAsync(IEnumerable<T> t, string path)
{
HttpResponseMessage response;
response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
t = await response.Content.ReadAsAsync<IEnumerable<T>>();
}
return t;
}
Not sure whats the issue,not getting result response = await client.GetAsync(path);.
I am able to get result with the same api and parameters when called from Session_Start event in Global.asax. Please let me know whats the issue and how can retrieve result from http.
I have resolved this issue by keeping the route config as it is.
Created a new Action filter and reroute the url based on access.
Placed this filter on the top of default route.
public class StartupFilter:ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var userAccessDetails = HttpContext.Current.Session["Role"] as UserRole;
if (userAccessDetails.HasAccessHome)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(
new
{
controller = "Home",
action = "Index"
}));
}
else if (userAccessDetails.HasAccessReport))
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(
new
{
controller = "Reports",
action = "Index"
}));
}
base.OnActionExecuting(filterContext);
}
}
I am trying to add some Routing rule in Global.ascx im my ASP.NET MVC application. I extend the IRouteHanlder, MVCHandler and registe the rule just as follow.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routes.MapRoute(
// "DefaultTT", // Route name
// "test", // URL with parameters
// new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
//);
RouteValueDictionary defaults = new RouteValueDictionary();
RouteValueDictionary constraints = new RouteValueDictionary();
RouteValueDictionary tokens = new RouteValueDictionary();
defaults.Add("controller", "home");
defaults.Add("action", "index");
defaults.Add("data", string.Empty);
constraints.Add("data", #"[a-zA-Z0-9\-]*");
tokens.Add("pageId", 0);
routes.Add(new Route("", defaults, constraints, tokens, new MyRouteHandler()));
}
public class MyRouteHandler : IRouteHandler
{
public System.Web.IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
{
return new MyMVCHanlder(requestContext);
}
}
public class MyMVCHanlder : MvcHandler
{
public MyMVCHanlder(RequestContext requestContext)
: base(requestContext)
{
}
protected override void ProcessRequest(HttpContext httpContext)
{
int i = 1;
int j = i + 1;
base.ProcessRequest(httpContext);
}
protected override void ProcessRequest(HttpContextBase httpContext)
{
int i = 1;
int j = i + 1;
base.ProcessRequest(httpContext);
}
}
But when I visit localhost:50112/ in my browser, the ProcessRequest method cannot be fired. I don't know why. Do you have any thought? Thank you.
I want to split my controller name..
For Example;
My controller name is For_ExpController.cs
and
I want my url like this;
http://localhost/For/Exp/Action
How can I define it on my RouteConfig.cs??
You could write a custom route:
public class MyRoute: Route
{
public MyRoute()
: base(
"{part1}_{part2}/{action}",
new RouteValueDictionary(new { controller = "for_exp", action = "index" }),
new RouteValueDictionary(new { part1 = #"[a-z]+", part2 = #"[a-z]+" }),
new MvcRouteHandler()
)
{
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var rd = base.GetRouteData(httpContext);
if (rd == null)
{
return null;
}
var part1 = rd.GetRequiredString("part1");
var part2 = rd.GetRequiredString("part2");
rd.Values["controller"] = string.Concat(part1, "_", part2);
return rd;
}
}
which will be registered in your Application_Start:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add("MyRoute", new MyRoute());
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
}
I have a number of controllers in application:
ApiV1Controller
ApiV2Controller
ApiV3Controller
...
Is it possible to map routes for them with single MapRoute statement to URLs like /api/v1/{action}?
You could write a custom route. Let's suppose that you have the following controllers:
public class ApiV1Controller : Controller
{
public ActionResult Index()
{
return Content("v1");
}
}
public class ApiV2Controller : Controller
{
public ActionResult Index()
{
return Content("v2");
}
}
public class ApiV3Controller : Controller
{
public ActionResult Index()
{
return Content("v3");
}
}
Now write a custom route:
public class ApiRoute : Route
{
public ApiRoute()
: base("api/{version}/{action}", new RouteValueDictionary(new { action = "index" }), new MvcRouteHandler())
{
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var rd = base.GetRouteData(httpContext);
if (rd == null)
{
return null;
}
rd.Values["controller"] = "Api" + rd.GetRequiredString("version");
return rd;
}
}
That could be registered in your Global.asax:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add("ApiRoute", new ApiRoute());
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
and that's pretty much it. Now you could play with urls:
/api/v1
/api/v2
/api/v3