Value not getting passed in url - asp.net-mvc-3

//In Controller this is what I have
public class AjaxController : Controller
{
[AcceptVerbs(new string[]{"GET"})]
public ActionResult FindRooms(string selectedBuilding)
{
return Json(new { Room = "x"}, JsonRequestBehavior.AllowGet);
}
}
//In Global.asax.cs I have
routes.MapRoute
(
"AjaxRoute1",
"Ajax/FindRooms/{selectedBuilding}",
new { controller = "Ajax", action = "FindRooms", selectedBuilding = "" }
);
If I browse to URL localhost/Ajax/FindRooms/SOMEBUILDING. The SOMEBUILDING is not getting passed to selectedBuilding parameter of FindRooms method. It is always null?? How can I fix this so that it works in both POST and GET?

As Mr TA suggested the other routes affects this. The order of routing is important.
I put the default route route at the end and works like a charm.!!
routes.MapRoute
(
"AjaxRoute1",
"Ajax/FindRooms/{selectedBuilding}",
new { controller = "Ajax", action = "FindRooms", selectedBuilding = "" }
);
routes.MapRoute
(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Related

url parameters missing after adding a comment and redirecting back to blog post

I am teaching myself asp .net mvc3 by creating a blog application. However, I have
problems with comment upload. It is a very subtle error in that everything works when a user leaves a comment. However, the url of the post changes.
So, a blog post has a url
http://localhost:49175/Blog/Details/3/Third-post
This is generated by the url route map here:
routes.MapRoute(
"BlogDetail", // Route name
"Blog/Details/{id}/{urlHeader}", // URL with parameters
new { controller = "Blog", action = "Details", id = UrlParameter.Optional, urlHeader = UrlParameter.Optional } // Parameter defaults
);
Now, when a user leaves a comment - he is directed to a comment controller:
[HttpPost]
public ActionResult Create(BlogDetailsViewModels viewModel)
{
if (ModelState.IsValid)
{
try
{
blogrepository.Add(viewModel.Comment);
return RedirectToAction("Details", "Blog", new { id = viewModel.Comment.BlogID });
}
catch (DataException)
{
ModelState.AddModelError("", "Unable to save comment. Try again, and if the problem persits then contact administrator.");
}
}
// If we got this far, something failed, redisplay form
return RedirectToAction("Details", "Blog", new { id = viewModel.Comment.BlogID });
}
}
However, when somebody leaves a comment - he is redirected back to
http://localhost:49175/Blog/Details/3
I know, as of now there is nothing in the RedirectToAction that passes the urlHeader info. However, I have tried a few things like:
return RedirectToAction("Details", "Blog", new { id = viewModel.Comment.BlogID, urlHeader = viewModel.Blog.UrlHeader });
However, it doesn´t seem to work.
This is the blog details controller:
//
// GET: /Blog/Details/5
public ViewResult Details(int id, string urlHeader)
{
var blogs = blogrepository.GetBlog(id);
var recentblogs = blogrepository.FindRecentBlogs(5);
var archivelist = blogrepository.ArchiveList();
BlogDetailsViewModels viewModel = new BlogDetailsViewModels { Blog = blogs, RecentBlogs = recentblogs, ArchiveList = archivelist };
return View(viewModel);
}
I am stuck for days on this.
-- Full route method as requested --
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"BlogDetail", // Route name
"Blog/Details/{id}/{urlHeader}", // URL with parameters
new { controller = "Blog", action = "Details", id = UrlParameter.Optional, urlHeader = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"BlogArchive", // Route name
"Blog/{year}/{month}", // URL with parameters
new { controller = "Blog", action = "Archive" }, // Parameter defaults
new { year = #"\d{4}", month = #"\d{1,2}", } // Parameter constraints
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
If your form does not contains data for viewModel.Blog.UrlHeader, it will be an empty string, even viewModel.Blog may be null.
You can add a parameter to your post action method, like this:
[HttpPost]
public ActionResult Create(BlogDetailsViewModels viewModel, String urlHeader)
And, in your view that renders the form, use this code to generate the form element:
#Html.BeginForm("Create","Blog",new{urlHeader=Model.Blog.UrlHeader})
Alternatively, you can add a hidden input in your form for the urlHeader. In this way, you don't have to do any of previous two updates.
#Html.HiddenFor(m=>m.Blog.UrlHeader)
Either way, make sure your Model.Blog.UrlHeader is not null or an empty string

Url.Action MVC3 not recognizing route parameter when building link

When adding custom routing constraints to my route parameters I am finding that it is breaking the Url.Action method I use to build my links. If the route constraint is simply a regular expression then the Url.Action method continues to recognize the parameter, however if it is a custom constraint which I define, Url.Action method gives my parameter as a request parameter.
Here is my route definition:
routes.MapRoute(
"Event",
"Events/{strDate}",
new { controller = "Events", action = "Index", strDate = DateTime.Today.ToString("yyyy-MM-dd") },
new { strDate = new IsValidDateConstraint() },
new[] { "MyProject.Controllers" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "MyProject.Controllers" }
);
The IsValidDateConstraint class inherits from IRouteConstraint and returns true or false if the strDate parameter parses correctly to a DateTime object:
public class IsValidDateConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (routeDirection == RouteDirection.IncomingRequest)
{
DateTime dt = new DateTime();
if (DateTime.TryParse(values["strDate"].ToString(), out dt))
return true;
}
return false;
}
}
Using the Url.Action method to build URL's:
#Url.Action("Index", "Events", new { strDate = ViewBag.CurrentDate.AddDays(1).ToString("yyyy-MM-dd") })
The resulting link is: /Events?strDate=2012-08-15
Everything routes correctly if I type in /Events/2012-08-15, it's just that the Url.Action method is not recognizing that strDate is a parameter defined in my route only when I apply my custom routing constraint. If I comment out the custom routing constraint then the Url.Action method maps the URL correctly.
Any ideas on why the Url.Action is not recognizing my route parameter when I have a custom route constraint defined?
You haven't shown how your IsValidDateConstraint looks like but make sure you are doing a culture invariant parsing for the yyyy-MM-dd format:
public class IsValidDateConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
DateTime date;
return DateTime.TryParseExact(
values[parameterName] as string,
"yyyy-MM-dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out date
);
}
}
Also make sure that this route is placed before the default route:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Event",
"Events/{strDate}",
new { controller = "Events", action = "Index", strDate = DateTime.Today.ToString("yyyy-MM-dd") },
new { strDate = new IsValidDateConstraint() },
new[] { "MyProject.Controllers" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
also DateTime.Parse(ViewBag.CurrentDate.ToString()) looks a wee-bit of a WTFkish code. If ViewBag.CurrentDate is already a DateTime you could directly write:
#Url.Action(
"Index",
"Events",
new {
strDate = ViewBag.CurrentDate.AddDays(1).ToString("yyyy-MM-dd")
}
)
Obviously a much better solution is to use view models:
#Url.Action(
"Index",
"Events",
new {
strDate = Model.CurrentDate.AddDays(1).ToString("yyyy-MM-dd")
}
)
UPDATE:
Now that you have shown your code the problem comes from the if condition you have put in your constraint:
if (routeDirection == RouteDirection.IncomingRequest)
When using the Url.Action helper this condition is never satisfied. Only when resolving an incoming url. So you will have to remove it if you want this constraint to work with url helpers.

Routing with areas and different parameters, misunderstanding

I have been confused all day, i have a routing in area and it looks like this.
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "admin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRouteLowercase(null, "Account/{action}",
new {controller = "Account"},
new {action = #"LogOff|LogOn|Create|Update|Delete|List"},
new[] {"WebUI.Areas.Admin.Controllers"});
context.MapRouteLowercase( //this works
"AdminUpdateCategoryView",
"admin/{controller}/{action}/{cid}",
new {area = "admin", controller = "Main", action = "UpdateCategory", cid = ""},
new {cid = #"\d+"},
new[] {"WebUI.Areas.Admin.Controllers"}
);
context.MapRouteLowercase(//this not works
"AdminCategoryListView",
"admin/Main/{action}/{page}",
new { action = "Category", page = "1" },
new {page = #"\d+"},
new[] {"WebUI.Areas.Admin.Controllers"}
);
context.MapRouteLowercase(
"Admin_Default", // Route name
"admin/{controller}/{action}/{id}", // URL with parameters
new {controller = "Category", action = "Index", id = UrlParameter.Optional} // Parameter defaults
);
}
}
I have wrote what works and what not, but if change between them the one that doesn't work, works and the other that works, don't work?
example:
first case-> /admin/main/updatecategory/1 --> works
/admin/main/category/1 --> not works
result: /admin/main/category/1?page=1
second case-> /admin/main/category/1 --> works
/admin/main/updatecategory/1 --> not works
result: /admin/main/updatecategory/1?cid=1
Here is my controller actions:
public ActionResult Category(int? page)
{
int pageIndex = page.HasValue ? page.Value : 1;
return View("Category", CategoryViewModelFactory(pageIndex));
}
public ActionResult CreateCategory()
{
return View();
}
public ActionResult UpdateCategory(int cid)
{
return View();
}
public ActionResult DeleteCategory(int? cid)
{
return View();
}
What is this problem and how to solve it?
I'm totally confused, Routing in ASP.MVC3 is e-logical.
Help?!
When routes are searched, the first one that matches your URL is used. AdminUpdateCategoryView will match any admin controller, and action. You provide a default cid of "", but that shouldn't matter because you're requiring that cid be a number below that. AdminCategoryListView will match any url that enters main. Because you provide a default page of 1, it doesn't even matter if no page is provided.
So if AdminCategoryListView is on top: every single route in admin/main will use this route.
If AdminUpdateCategoryView is on top every route in admin that reaches this route and has a numerical cid value parameter will use it.
I'd recommend putting AdminCategoryListView on top because it's the more specific route. Either remove page="1" (depends on if you want to provide a default), or replace {action} with "category" so your other routes don't use this route. Also you should provide a default controller of main, otherwise it will assume the controller you're currently using is the correct one.
context.MapRouteLowercase(
"AdminCategoryListView",
"admin/Main/category/{page}",
new { action = "Category", controller = "Main" },
new {page = #"\d+"},
new[] {"WebUI.Areas.Admin.Controllers"}
);
//Put AdminUpdateCategoryView here

RedirectToAction and Routing not passing parameter correctly

I am trying to use a RedirectToAction method after a selfposting Action (which passes IsValid). The redirect happens fine but the parameter I am attempted to pass to the action is always null.
[HttpPost]
public ActionResult UploadForm(UploadFormViewModel formVM)
{
if (!ModelState.IsValid)
{
return View(formVM);
}
return RedirectToAction("UploadConfirm", new { confirmVM = new UploadConfirmViewModel() });
}
public ActionResult UploadConfirm(UploadConfirmViewModel confirmVM)
{
return View(confirmVM);
}
And here is my routing
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"UploadConfirm",
"{controller}/{action}/{confirmVM}",
new { controller = "EnrollmentUpload", action = "UploadConfirm" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "EnrollmentUpload", action = "UploadForm", id = UrlParameter.Optional } // Parameter defaults
);
Remove the new{} in your return statement:
return RedirectToAction("UploadConfirm", new UploadConfirmViewModel());
I also did not add an extra route to the Routecollection

URL Routing: How do I have a string as my id?

I would like to receive a string as the id in the URL. Here is an example:
http://www.example.com/Home/Portal/Fishing
I would like to have Fishing in my id. But I cannot achieve it with the following code:
Code from my Controller:
public ActionResult Portal(string name)
{
// some code
ViewData["Portal Name"] = name;
}
Code from Global.asax.cs:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Just change the argument to id:
public ActionResult Portal(string id)
{
// some code
ViewData["Portal Name"] = id;
}
The argument will be bound if it has the same name as the route value token. So an alternate approach would be to keep the argument named name and change the route:
public ActionResult Portal(string name)
{
// some code
ViewData["Portal Name"] = name;
}
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{name}", // URL with parameters
new { controller = "Home", action = "Index", name = UrlParameter.Optional } // Parameter defaults
);
I would choose using id, though, as it's the more standard approach.

Resources