Unit Test ASP MVC Route with Constraint - asp.net-mvc-3

I have a route that is defined like this:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional, area = "" }, // Parameter defaults
new { home = new HomePageConstraint() }
);
public class HomePageConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
return !httpContext.Request.RawUrl.StartsWith("/home", StringComparison.InvariantCultureIgnoreCase);
}
}
And I am trying to test it like this:
[Test]
public void Home_Load_Homepage()
{
"~/".ShouldMapTo<HomeController>(x => x.Index());
}
The problem I have is that the httpContext is null, so the test fails. how can I inject http context into a constraint?

In the end I did this:
var context = new FakeHttpContext("~/");
var fakeRequest = new FakeRequest("~/", new Uri("http://localhost/"), new Uri("http://localhost/"));
context.SetRequest(fakeRequest);
var route = RouteTable.Routes.GetRouteData(context);
route.ShouldMapTo<HomeController>(x => x.Index());

Related

Url.RouteUrl returning empty

I´m trying to get full URL but the RouteUrl is returning empty.
In the View, I´m calling like that:
alert('#Url.RouteUrl("Api", new { controller = "Parametros", id = "" })');
Here is my routes configurations:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapHttpRoute(
name: "Api",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Usuario",
action = "Login", id = UrlParameter.Optional }
);
}
and my controller:
public class ParametrosController : ApiController
{
ISistemaService _sistemaService;
public ParametrosController(Empresa empresa, ISistemaService sistemaService)
{
_sistemaService = sistemaService;
}
public PagedDataModel<ParametroDTO> Get(
[FromUri]ParametroFiltro filter, int page, int pageSize)
{
int total = 0;
var list = _sistemaService.Paging(filter, page, pageSize, out total);
return new PagedDataModel<ParametroDTO>(page, pageSize, total, list);
}
public ParametroDTO Get(string codigo)
{
return _sistemaService.GetParametroPorCodigo(codigo);
}
}
Add httproute = "" to the routeValues:
alert('#Url.RouteUrl("Api",
new { httproute = "", controller = "Parametros", id = "" })');

how to handle hange my routes value?

i have an area and change my route to this
public class WeblogsAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Weblogs";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Weblogs_default",
"Weblogs/{controller}/{action}/{blogName}/{post}",
new { action = "Index",
blogName = UrlParameter.Optional,post=UrlParameter.Optional}
);
}
}
and it is my index
public ActionResult Index(string blogName,int post)
{
return View();
}
it works fine by this:
http://localhost:2927/Weblogs/Blogs?blogName=Myco&Post=3
but works not by
http://localhost:2927/Weblogs/Blogs?blogName=Myco
what is the problem?
how can i change my rout to works with this URL:
http://localhost:2927/Weblogs/Blogs/Myco/3
"myco" is blog name and 3 is post number.
is it possible?
Remove your action and controller tokens from your route. Modify it to be like so:
context.MapRoute(
"Weblogs_default",
"Weblogs/Blogs/{blogName}/{post}",
new { action = "Index",
Controller = "Blogs",
blogName = UrlParameter.Optional,
post=UrlParameter.Optional}
);

hypen in MVC 3 routes

Here is my desired url format: /product-24-hid-35wh4-cx-dsgtx
How can I map this URL to my action method:
public ActionResult Product(int id)
Here is my routing code:
routes.MapRoute(
"ProductDetail",
"product-{id}-{name}",
new { controller = "product", action = "detail", name = UrlParameter.Optional },
new string[] { "SphereLight.Controllers" }
);
However, it does not work; I used phil haack's routedebugger to test this route, and below is the result:
Key Value
name dsgtx
id 24-hid-35wh4-cx
controller product
action detail
Only id = 24 is correct.
In one word, I need a route to match:
/product-24
/product-24-
/product-24-hid-35wh4-cx-dsgtx
Try to add constraints in your MapRoute:
routes.MapRoute(
"ProductDetail",
"product-{id}-{name}",
new { controller = "product", action = "detail", name = UrlParameter.Optional },
new { id = #"\d+" }, // <-- change it for #"[^-]+", if it can be non-digit
new string[] { "SphereLight.Controllers" }
);
UPDATE:
Finally got it.
The main problem is that you can't use parameters which contains the same separator.
For example, the example above will work with /product-24-nm, but not with product-24-nm-smth.
So, let's try this solution:
I've made it on the default routing, you can make it your way
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new MyRouteHandler()
).RouteHandler = new MyRouteHandler();
Implementation of MyRouteHandler:
public class MyRouteHandler : MvcRouteHandler
{
private static readonly Regex ProductPattern = new Regex(#"product\-(\d+)\-?(.*)");
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var match = ProductPattern.Match(requestContext.RouteData.Values["controller"].ToString());
if (match.Length > 0)
{
requestContext.RouteData.Values["controller"] = "Home";
requestContext.RouteData.Values["action"] = "Detail";
requestContext.RouteData.Values["id"] = match.Groups[1].Value;
requestContext.RouteData.Values["name"] = match.Groups[2].Value;
}
return base.GetHttpHandler(requestContext);
}
}
So, the main idea is to check if the values matches our pattern product-id-name in the handler, and not trying to make it in MapRoute.
Hope this helps.

ASP.NET MVC - How to register custom route?

I've created a custom Route and registered it in Global.asax like this:
routes.Add(
null,
new SeoRoute(
"foo/{id}/{title}",
new { controller = "Foo", action = "Details" }
));
Since I'm using Areas in my application, I have to set Namespaces for each Route.
With regular routes, I do it like this:
routes.MapRoute(
null,
"foo",
new { controller = "Foo", action = "Index" },
new string[] { "Boo.Web.Controllers" }
);
But how can I set namespaces for custom routes?
Any help would be greatly appreciated!
I used ILSpy too see how MapRoute works.
I didn't set DataTokens value. Here's the solution:
Route class:
public class SeoRoute : Route
{
public SeoRoute(string url, object defaultValues, string[] namespaces)
: base(url, new RouteValueDictionary(defaultValues), new MvcRouteHandler())
{
if(namespaces != null && namespaces.Length > 0)
{
DataTokens = new RouteValueDictionary();
DataTokens["Namespaces"] = namespaces;
}
}
...
}
Global.asax:
routes.Add(
null,
new SeoRoute(
"foo/{id}/{title}",
new { controller = "Foo", action = "Details" },
new string[] { "Boo.Web.Controllers" }
));

MapRouting default querystring values?

I have this route map (notice that topicName is ignored):
routes.MapRoute(
"Topics", // Route name
"Topic/{topicName}/{action}",
new { controller = "Topic", action = "AddQuestion" });
And I want it to defaultly map to this Url:
http://localhost:51421/Topic/SomeName/AddQuestion?topicId=1 (or if that's not possible,to this url: http://localhost:51421/Topic/SomeName/AddQuestion/topicId/1)
(which should invoke this action:
public ActionResult AddQuestion(int topicId)
{
return View();
}
)
But either way I need all this data in the url.
What's the correct way to do that?
You could add a default route:
routes.MapRoute(
"Topics",
"Topic/{topicName}/{action}/{topicId}",
new { controller = "Topic", action = "AddQuestion", topicId = "1" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{topicId}",
new { controller = "Topic", action = "AddQuestion", topicId = "1" }
);

Resources