MVC ActionLink not displaying correctly - c#

My goal is have the link appear as mydomain.com/viewPhone/1
Currently, the link is appearing as Home/phoneCatalog , and without displaying my ID
ROUTING
routes.MapRoute(
name: "phoneCatalog",
url: "viewPhone/{phoneID}",
defaults: new { controller = "Home", action = "phoneCatalog",}
);
CONTROLLER
public ActionResult phoneCatalog(int phoneID)
{
//CODE HERE
}
MVC VIEW
<span class="floatL w100">#Html.ActionLink(title, "phoneCatalog", "Home", new { phoneID = orderItem.phoneID }, null)
</span>

Use #Html.RouteLink instead. You probably still have the fall-back {controller}/{action}/{id} route defined.
#Html.RouteLink(title, "phoneCatalog", new { phoneID = orderItem.phoneID })

You should use attribute routing. It gives you more flexibility if you like different names for your actions rather than default values.
It is easy to use.
Check out:
http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx
[Route("viewPhone/{phoneID:int}")]
public ActionResult phoneCatalog(int phoneID)
{
//CODE HERE
}
Try this.

Related

ASP.NET route issue

I have the following in my RouteConfig.cs file
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Home Controller has the following:
[Route("NewIncident")]
public ActionResult NewIncident()
{
var viewModel = new IncidentFormViewModel();
viewModel.NextPage = 2;
return View("NewIncident",viewModel);
}
[Route("EditIncident/{id?}")]
public ActionResult EditIncident(int? id)
{
return View("EditIncidentPage" + id);
}
[Route("SaveIncident")]
public ActionResult SaveIncident(IncidentFormViewModel incidentviewmodel)
{
return RedirectToAction("EditIncident/" + incidentviewmodel.NextPage);
}
From my index view, I can click a button that has the #Html.ActionLink as follows:
#Html.ActionLink("New Incident", "NewIncident", "Home", null, new { #class = "btn btn-primary" })
I access the site at http://sitename/ and it loads my index page. I can click the New Incident button and it loads http://sitename/NewIncident just fine, but when I click the Save button on the New Incident form, it calls the SaveIncident function just fine, but when it hits the return RedirectToAction("EditIncident/" + incidentviewmodel.NextPage); it sends me to http://sitename/Home/EditIncident/2 instead of just http://sitename/EditIncident/2.
Any idea why its adding the /Home in there?
The parts of the URL are http://sitename/Controller/Action/Parameter.
Your EditIncident ActionResult lives inside your Home Controller, and so you will therefore always see Homein front of EditIncident.
When you redirect to another Action, you can specify which controller to look for the ActionResult in with RedirectToAction("ActionName", "ControllerName"). If no Controller is specified, it assumes you want to use the same controller that you are currently in.
yes, Tot Zam are ok, and you need to create an action result method on your controller, this should be bind with a view
Found the issue.
Apparently I need to use Redirect(), not RedirectToAction() for my purposes.
Once I changed this, it rendered the correct URL without adding /Home to it

MVC weird routing behaviour

I have a weird problem with some routing in MVC. Here's my scenario:
The user gets presented to the front page, once visiting the site: testproject.com:57416/Home.
The user has a menu on the left side, with the menu item "Solutions".
The user presses the menu item "Solutions" and the menu item expands, showing 5 sub items.
The user presses the sub item "Demo", and redirects to testproject.com:57416/Solutions/SetLayout?layoutString=page1%7Csize15
As the param layoutString is defined, the grid (DevExpress) know how to filter the data to show.
The grid is presented to the user, and (s)he can now navigate around the grid, manipulating the layout.
The user now wants to see the clean Demo layout again, and (s)he presses the menu item "Solutions" -> sub item "Demo".
The action ActionResult SetLayout(string layoutString) is not hit in this case, but instead the action ActionResult Index() is hit, thereby not setting the layout as the layoutString is not sent in as a param
The url that the user is redirected to, looks like this: testproejct.com:57416/Solutions?undefined=undefined
This might be a bit tiresome to read through, but it's the best way possible for me to explain my scenario as I have never seen anything like this before in MVC. I truly have no idea what's going on, and why the action ActionResult SetLayout(string layoutString) is not hit the second time.
I suppose I should show some code so we can narrow down the possibilities.
_Layout.cshtml (has menu items)
<li class="has-submenu">
Solutions
<ul class="nav sub-menu-list">
<li>
#Html.ActionLink("Demos", "SetLayout", "Solutions", new { layoutString = "page1|size15" }, null)
</li>
</ul>
</li>
ActionResult SetLayout(string layoutString)
public ActionResult SetLayout(string layoutString)
{
Session["Layout"] = layoutString;
return RedirectToAction("Index", "Solutions");
}
ActionResult Index()
public ActionResult Index ()
{
using(var db = new DataBasecontext())
{
var list = db.Solutions.ToList();
return View(list);
}
}
EDIT
I've found out that this only happens when I'm inside the same controller. The controller holding the action ActionResult SetLayout(string layoutString) is the SolutionsController. If I'm coming from, let's say the AccountController everything works fine, but changing from SolutionsController to another action in the SolutionsController doesn't work.
Come to think of it, could have something to do with my map routes?
routes.MapRoute(
name: "ControllerIdActionId",
url: "{controller}/{id}/{action}/{id2}",
default : new { id2 = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
default : new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Solutions",
url: "{controller}/{id}/{action}",
default : new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Seems that the layoutString parameter has missing parameter value on its second firing, thus empty string value inserted into Session key (and Javascript function related to that Session treat the empty string as undefined).
public ActionResult SetLayout(String layoutString)
{
// Test if the string is null or empty before filling session key,
// if it is empty one, leave the session key as is
if (!String.IsNullOrEmpty(layoutString)) {
Session["Layout"] = layoutString;
}
return RedirectToAction("Index", "Solutions");
}
Perhaps this is not the best way to do, I just viewed from SetLayout method perspective to fill Session key with proper query string.
Pass 5th parameter as null in your actionlink as below:
#Html.ActionLink("Demos", "SetLayout", "Solutions", new { layoutString = "page1|size15" },null)
I have not tested it but may be it is the issue..
I managed to solve the problem on my own.
I'm not quite sure what the issue was, but changing the Html.ActionLink() into Html.RouteLink()'s I was able to define what MapRoute to use.
I solved it by using the following MapRoute
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
)
I could then use the Html.RouteLink like so:
Html.Routelink("Demos", //Display text
"Default", //The MapRoute to use
new { layoutString = "page1|size15|", //The param (layoutString)
controller = "Solutions", //The controller
action = "SetLayout" }) //The action
I made no changes to the action:
public ActionResult SetLayout(string layoutString)
{
Session["Layout"] = layoutString;
return RedirectToAction("Index", "Solutions");
}

MVC Partial Views, GET and routing

Good Day,
This is my first question, so please be kind. I have just made the move from forms to mvc.
I have made the following route (below). I constructed a partial view that also contains 2 other partial views (as seen below).
When submitted the url will be something like 'Find/Index?Region=3&Interest=1'
What is the best way to create a friendly url matching the route defined
'Find/Index/In-Wales-3/Sport-1'? I could post and then redirect, but I thought this maybe inefficient. A better approach maybe to use jquery?
Please also indicate if the design used is correct or if it could be improved upon? The reason for separating the views, is because they are used on multiple views.
Thanks in advance!
Route Config
routes.MapRoute(
name: "Find",
url: "{controller}/{action}/In-{region}-{rid}/{interest}-{iid}",
defaults: new { controller = "Find", action = "Index", region = UrlParameter.Optional,
rid = UrlParameter.Optional,
interest = UrlParameter.Optional,
iid = UrlParameter.Optional
});
Partial View That Is Rendered On Master Page
#model SimpleFriendFinderModel
<h1>Find</h1>
<div>
#using (Html.BeginForm("Index", "Find", FormMethod.Get))
{
#Html.Partial("_RegionDropDown", #Model.Regions)
#Html.Partial("_InterestDropDown", #Model.Interests)
<div>
<button>SEARCH</button>
</div>
}
</div>
Region Partial View
#model IEnumerable<Region>
<select id="Region" name="Region">
<option>REGION</option>
#{ foreach(var item in Model) {
<option value="#item.RegionID">#item.RegionName</option>
}
}
</select>
The other partial view is a replica of Region but obviously a different model.
For the PartialViews; it is the way to go if you re-use it on other pages. You can think of it a bit as 'encapsulated logic'.
UPDATE: Ignore the above if you are just using a partial view for a dropdownlist. There is a HtmlHelper, Html.DropDownListFor() for that.
For the first part; the order is relevant:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Pretty",
url: "{controller}/{action}-{id}/Something",
defaults: new { controller = "Test", action = "Foo", id = UrlParameter.Optional }
);
//default route
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
for example will work if you would like to format the URL like:
http://local:23802/Test/Foo-5/Something

How do I get a pretty URL when creating a link in a Razor View?

I'm asking how to do a link with #Url.Action in a Razor view to make a link like
Controller/Action/123
I already made #Url.Action("Action","Controller", new { #ViewBag.ID }) but it makes me a link like
Controller/Action?ID=123
How do I make a URL without the querystring in the razor view?
Try:
#Url.Action("actionname", "controllername", new { id = ViewBag.Id})
I think the problem is just that you haven't specified that the value in your route parameters collection is the "id". Of course, I'm assuming that you're using the default route configuration in RegisterRoutes.
Tip: you can also use Html.ActionLink() which saves you the trouble of creating an <a> tag yourself:
#Html.ActionLink("linkText", "actionName", "controllerName", new { id = ViewBag.ID }, null);
This will generate an <a> tag with the linkText and the same url as Url.Action() which you can see in Jeff's answer.
Note: don't forget to add null as the last parameter, otherwise it will use the wrong overload and use the anonymous type as htmlAttributes.
Use Url.RouteUrl(String, Object) and notUrl.Action()
Use the default route name.. which must be Default
so your code should be :
#Url.RouteUrl("Default", new {controller = "SomeControler", action = "SomeAction" , id = #ViewBag.ID })
Doing that will give you url as follows : SomeController/SomeAction/5 (assuming ID was 5)
This happens because of the by default the project mvc template contains a Default route as follows :
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
You can create more fancy urls if you wish or if you need more parameters, by adding more routes into routing table
here's the description : http://msdn.microsoft.com/en-us/library/dd505215(v=vs.108).aspx
#Url.Action("Action/" + #ViewBag.ID,"Controller")

MVC3 Route/redirect problem

My application is multilingual and I wrote the following route in order to handle the languages:
routes.MapRoute(
"Default", // Route name
"{language}/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index",
language = "pt", id = UrlParameter.Optional }, // Parameter defaults
new { language = #"(pt)|(es)|(en)" }
);
This works for domain.com and domain.com/pt/home/index. However, if I type domain.com/home/index it fails (404).
The desired behavior would be it being redirected to domain.com/pt/home/index (pt is the default language).
Whats the best way to achieve this? I've been reading a lot about routes and ActionFilters but nothing seems quite right.
i would suggest using custom route handler like following
public class LanguageRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
IRouteHandler handler = new MvcRouteHandler();
var vals = requestContext.RouteData.Values;
if(vals["language"] == null)
{
vals["language"] = "pt";
}
return handler.GetHttpHandler(requestContext);
}
}
and have another route without language route value and set its route handler (global.asax)
routes.MapRoute(
"Default2", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
).RouteHandler = new LanguageRouteHandler();
This will not redirect Home/index to pt/home/index yet it will provide language = "pt" to your index action method (and all others). if you want to redirect you can implement an actionfilter but redirecting will create problems with post requests. For example when you post a form to /home/index and suppose it is redirected by action filter, the redirected request will lose posted form data
You need two routes, the other one without the language, or add the language parameter at the end
Try this
routes.MapRoute(
"Default", // Route name
"{language}/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new { language = #"(pt)|(es)|(en)" }
);
and modify your action in this way
public ActionResult Index([DefaultValue("pt")] string language)
{
...
}

Categories