Asp.net mvc won't take the razor parameter - c#

I'm developing on a school project where it has gone great so far but the problem has finally arrived.
I have this method in my homecontroller:
[HttpPost]
public ActionResult GetSeatsInShow(int showId)
{
...
return View(realSeatList);
}
In my view I use razor to parse a parameter to the controller and the controller should return the result in an address like this:
http://localhost:1499/Home/GetSeatsInShow/236
That is what it does if I do it on my other controller method called Shows on the following URL:
http://localhost:1499/Home/Shows/1
But on the GetSeatsInShow method will I need to place ?showId= like to snippet right under:
http://localhost:1499/Home/GetSeatsInShow/?showId=236
My razor ActionLink looks like this:
#Html.ActionLink("Vælg", "GetSeatsInShow", new { id = item.Id })
Can't seem to find the problem aftersome the Show method works fine with the same results as the one that doesn't work.

You have a few options.
You're currently passing the parameter as id, not showId, whereas your controller expects a parameter named showId. As a result, by updating your anonymous type you can pass the correct parameter name.
#Html.ActionLink("Vælg", "GetSeatsInShow", new { showId = item.Id })
Alternatively, you can simply pass "id" in your querystring and allow the default MVC binding to work it's magic if you update your controller:
#Html.ActionLink("Vælg", "GetSeatsInShow", new { id = item.Id })
[HttpPost]
public ActionResult GetSeatsInShow(int id)
{
...
return View(realSeatList);
}

You can try this
#Html.ActionLink("Vælg", "GetSeatsInShow", new { id = item.Id, showId = item.Id })

you are taking an input of showId in GetSeatsInShow and in the razor you are passing in id
[HttpPost]
public ActionResult GetSeatsInShow(int id)
{
...
return View(realSeatList);
}

Related

In MVC, why does my controller need to receive a "new { id = restaurant.Id }", as opposed to "restaurant.Id"? Are the not both simply int's?

So my mvc controller method here take an int id as an argument. Im wondering why new "{ id = restaurant.Id}" is required and "restaurant.Id" is not sufficient.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Restaurant restaurant)
{
if (ModelState.IsValid)
{
db.Update(restaurant);
return RedirectToAction("Details", new { id = restaurant.Id });
}
return View(restaurant);
}
That is because MVC expects an object from which to retrieve the values to bind to the action parameters. In other words, you could do:
return RedirectToAction("Details", restaurant);
Mvc will crawl your object for properties that match the name and type of your action's arguments and should therefore bind to the restaurant's 'Id' property.
If you just pass the restaurant's Id, though, MVC will crawl the type of whatever you restaurant's id property is.
Hope this helps. If it does, please mark it as the answer ;)

Passing parameter to controller in MVC with no changes in url

I have a controller:
public ActionResult Index(string id)
{
ViewBag.ReloadedFromEmailForm = id;
return View();
}
The controller can be called from RouteConfig (as its default) with param id = null and can be called from some other controller which is returning
return RedirectToAction("Index", "Home", new {id = 1});
Now I want to get that id = 1 but in my url when I turn on app, to set just like regular without any param.
How to achieve that?
Now: localhost:8888/Index/1
What I want: localhost:8888/Index/ (but still I want to fill in ViewBag).
Solved. I didn't realize that property name id already in a route config,and automatically maps in url. All I needed to do was to change my prop to anything else, like foobar :)

Cannot generate correct links

I have the following code in a razor page:
#Url.Action("ArticleDetails", "Information", new { slug = article.Slug })
The page url where this code is placed has the form of http://localhost/category/6/category-name where 6 is the ID of the category
In the InformationController I have the following actions:
[HttpGet("article/{id}/{slug}")]
public IActionResult ArticleDetails(int id, string slug)
{
// some code ...
return View(data);
}
[HttpGet("article/{slug}")]
public IActionResult ArticleDetails(string slug)
{
// some code ...
return View(data);
}
How can I reach URL of form article/article-slug because #Url.Action(...) that I have in the page always try to reach controller action with id even if ID is not supplied as an anonymous type.
Links take the form of article/6/article-slug instead I want them to be article/article-slug without removing action with id in the controller.
I have noticed that 6 is from the id of the category. Also if I delete the controller action with Id i get the correct format of URL.
When resolving the action you're linking to, the IUrlHelper instance is using the current value of id in your current route (http://localhost/category/6/category-name), which has a value of 6, as you stated in your OP. Because there exists an ArticleDetails action that takes both an id and a slug (which you provide explicitly), the ArticleDetails action that takes both of these parameters is selected.
In order to resolve this, there are a couple of options. The first option is to clear out the RouteData value once you've used it in the action invoked when reaching http://localhost/category/6/category-name. In order to do that, you can use the following code within said action:
RouteData.Values.Remove("id");
I'm not a fan of doing it this way, but it does work. IMO, a better approach would be to simply use different names for the id parameter: e.g. categoryId and articleId in the respective controllers. This both fixes your issue and makes the code more readable in the corresponding actions. Your ArticleDetails action would simply change to:
[HttpGet("article/{articleId}/{slug}")]
public IActionResult ArticleDetails(int articleId, string slug)
{
// some code ...
return View(data);
}
Routing can be finicky when trying to do overloads like this. Your best bet is to use named routes:
[HttpGet("article/{id}/{slug}", Name = "ArticleDetailsIdSlug")]
public IActionResult ArticleDetails(int id, string slug)
[HttpGet("article/{slug}", Name = "ArticleDetailsSlug")]
public IActionResult ArticleDetails(string slug)
Then, in your view:
#Url.RouteUrl("ArticleDetailsSlug", new { slug = article.Slug })
Now, the routing framework doesn't have to try to figure out which route you actually want (and guess incorrectly apparently), as you'd told it exactly which route to use.

Unable to retrieve querystring data

In my bus service MVC project I need to be able to display a bus route stops only when i go to the route table. I have this ActionLink sending the querystring and the page to the route table: #Html.ActionLink("Route Stops", "index", "snRouteStops", new { id=item.busRouteCode}, null)
But when I get to my bus route stops controller I need it to throw me back to the route lists if there isn't one selected. This part works fine but when I click a route to view the stops nothing happens. Here is my code in the actionResult of the busRouteStops controller:
public ActionResult Index()
{
string busRouteCode = "";
if (string.IsNullOrWhiteSpace(Request.QueryString["busRouteCode"]))
{
if (Request.Cookies["busRouteCode"] == null)
{
return RedirectToAction("index", "snBusRoutes");
}
else
{
busRouteCode = Request.Cookies["busRouteCode"].ToString();
}
}
else
{
busRouteCode = Request.QueryString["busRouteCode"].ToString();
}
var routeStops = db.routeStops.Include(r => r.busRoute).Where(r => r.busRouteCode == busRouteCode).Include(r => r.busStop);
return View(routeStops.ToList());
}
}
Your main issue is that you are looking for a query string with the name busRouteCode, but your action link is not setup to provide a query string with that name. Your action link -
#Html.ActionLink("Route Stops", "index", "snRouteStops", new { id=item.busRouteCode}, null)
is configured to send the busRouteCode as a parameter with the name id. That means that the URL will look like this:
/snRouteStops/Index?id=myBusRouteCode
Thus, there is no query string with the name busRouteCode
You can do a few things to clean this up.
Standard routing in MVC is configured to use /Controller/Action/id. You can update your index action to be aware that an Id is coming by updating the action method.
//appears id is a string based on your code
public ActionResult Index(string id)
{
string busRouteCode = "";
if(string.IsNullOrEmpty(id))
{
if (Request.Cookies["busRouteCode"] == null)
{
return RedirectToAction("index", "snBusRoutes");
}
else
{
busRouteCode = Request.Cookies["busRouteCode"].ToString();
}
}
else
{
busRouteCode = id;
}
var routeStops = db.routeStops.Include(r => r.busRoute).Where(r => r.busRouteCode == busRouteCode).Include(r => r.busStop);
return View(routeStops.ToList());
}
}
Change your action link to send the busRouteCode as a parameter named busRouteCode.
#Html.ActionLink("Route Stops", "index", "snRouteStops", new { busRouteCode=item.busRouteCode}, null)
This will generate a link that looks like:
/snRouteStops/Index?busRouteCode=myBusRouteCodeValue
However you proceed, you should not really ever have to use Request.QueryString[] in your MVC controller actions. By configuring your action method to be looking for those query string values(like I did in example one), you can now get strongly typed parameters in your action methods as opposed to the string values in the QueryString[] dictionary. This is especially helpful when expecting an integer as a query string value for instance. The model binder will take care of ensuring that query string value is actually an integer and not a string.
This code {id=item.busRouteCode} generates query like that:
http://snRouteStops/Index?id=somedata
where somedata = item.busRouteCode.
Try to look for id in query string or just add id to action params, like that:
public ActionResult Index(string id)

Route is matching on parameter, not action name / View isn't returning properly

I want to create a url like that below:
www.mywebapp.com/Users/Profile/john
I have the UsersController controller and the Profile action, which returns a ViewResult to the Profile page.
I've created a route to manage it:
routes.MapRoute(
name: "ProfileRoute",
url: "Users/Profile/{username}",
defaults: new { controller = "Users", action = "Profile", username = UrlParameter.Optional }
);
The first question is: If i change {username} by {id}, it works. When I put {username} like parameter, the action gets NULL in the parameter. Why this?
Here's my action called Profile:
[HttpGet]
public ActionResult Profile(string id) {
if (UsersRepository.GetUserByUsername(id) == null) {
return PartialView("~/Views/Partials/_UsernameNotFound.cshtml", id);
}
return View(id);
}
I've added a View page to show the user profile. However, when the method ends its execution, I got another error:
The view 'john' or its master was not found or no view engine supports the searched locations.
The following locations were searched:
~/Views/Users/john.aspx
~/Views/Users/john.ascx
...
The second question is: The page I have to show is Profile, not a page with the username's name. Why is it happening?
You are getting this error because you are passing a string (id) to the View function, this overload searches for a view with the name passed in the string (in this case the username).
if you are simply trying to pass the username directly to the view you can use something like a ViewBag, so your code should look like this:
public ActionResult Profile(string id) {
if (UsersRepository.GetUserByUsername(id) == null) {
return PartialView("~/Views/Partials/_UsernameNotFound.cshtml", id);
}
ViewBag.Username=id;
return View();
}
I might be reading this incorrectly, but if you change the name of the required parameter from
id to username, it shouldn't return null
[HttpGet]
public ActionResult Profile(string username) {
if (UsersRepository.GetUserByUsername(username) == null) {
return PartialView("~/Views/Partials/_UsernameNotFound.cshtml", id);
}
return View(username);
}

Categories