Here is the hyperlinked code I am generating to show a list of merchants:
<td>
#Html.ActionLink(Html.DisplayFor(modelItem => item.MerchantName).ToHtmlString(), "ViewMerchant", "Merchants")
</td>
What I would like for it to do is to take me to a new page where it shows just the information on the merchant selected (address, webaddress, etc), so a ViewMerchant page in my Merchants View folder.
Can I grab the MerchantID in this ActionLink? If so how would that code look in the above ActionLink?
Secondly in the View Merchants page if anyone could link me to a site that would explain how to build that so the page gets populated with the merchant info would be ideal.
You can pass the MerchantID as a route value as follows:
#Html.ActionLink("Link text", "ViewMerchant", "Merchants", new { id = item.MerchantID }, null )
Where ViewMerchant is the name of your action instide MerchantsController
And here is a small sample to your details action:
public ActionResult Details(int id)
{
Merchant merchant = db.Merchants.Find(id);
return View(merchant);
}
Of course, you should use ViewModels instead of passing your model to the view. But that's another matter on which you can find many information online. Here is one link to start reading about it.
Related
I am a beginner and I am going through some tutorials in my MVC. So, I came across two scenarios.
Scenario 1.
I had to pass some data to my view on post and then send that data as hidden field. Here is the code.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ForgotPassword(ForgotPasswordMV viewModel)
{
if (ModelState.IsValid)
{
return RedirectToAction("VerifyToken", new { emailId = viewModel.EmailId });
}
^^ USING ANONYMOUS OBJECTS
return View();
}
public ActionResult VerifyToken(string emailId = null)
{
VerifyTokenMV viewModel = new VerifyTokenMV
{
EmailId = emailId
};
return View(viewModel);
}
VerifyToken View
#using (#Html.BeginForm("VerifyToken", "Security"))
{
#Html.HiddenFor(m => m.EmailId)
<button class="btn btn-primary">Continue</button>
}
Works Perfectly fine. I am able to receive values of EmailId. So far so good.
Scenario 2.
Needed to open a partial view from Main view, here is the snippet.
Main cshtml file
<div class="abc">
#Html.Partial("../Widget/Customize", Model.Unit, new ViewDataDictionary() { { "ElementName", "UnitWidget" } })
</div>
partial cshtml file
#{
string custWidgetElementName = ViewBag.ElementName;
}
// some html code below
Observation:
In scenario 2 why have I used ViewDataDictionary. Although both example works perfectly fine. But is there any reason that I had to use ViewDataDictionary. In scenraio 1 can we use ViewDataDictionary? If Yes, then which one is optimum solution.
Question: When I need to pass values shall I use new {key : value} or use ViewDataDictionary or there is no corelation? Instead of ViewDataDictionary can I use anonymous object in Senario 2
Your two scenarios are totally different. They are not doing the same thing.
In scenario 1 when using this line:
return RedirectToAction("VerifyToken", new { emailId = viewModel.EmailId });
A new URL is genrated and sent back to the client (the browser) with HTTP Code 301 or 302. When received the browser will re-contact your application wiht the received URL. With that URL, your application will execute the associated action. In your case, the client's browser will call VerifyToken action with the emailId parameter setted when you call RedirectionToAction into ForgotPassword action. So using RedirectionToAction method is just telling that method to generate a new URL with parameter defined in the anonymous type.
In scenario 2 is completely different to scenario 1. With this line:
#Html.Partial("../Widget/Customize", Model.Unit, new ViewDataDictionary() { { "ElementName", "UnitWidget" } })
You're telling your view to inject the partial view which path is ../Widget/Customize. Because that partial view the strongly typed, you passed Model.Unit as an second parameter. You use also a third parameter new ViewDataDictionary() { { "ElementName", "UnitWidget" } } because your partial seems to internally need to access to the dynamic property ViewBag or dictionary property ViewData of your view.
Conclusion:
In scenario 1 you are just telling the client's browser to go to the new URL you have generated after requesting ForgetPassword URL. We just call that a rediretion.
In scenario 2, you're just rendering a partial view into a view. The client's broswer doesn't know anything what's going on with partial views they don't know if they exist.
I have a view that has multiple partial views on it. It is a settings page. They can click a site on the left panel, ad it will display all the settings for managing that site in the partial view on the page. When I build the links of the sites, I use the following Razor code as an example:
List<Site> siteList = Site.GetSites(new SiteQuery());
foreach (Site site in siteList)
{
<li>#Html.ActionLink(#site.Name, "SelectSite", "SettingsController", new { id = Model.EnvironmentID, siteId = #site.SiteID}, null)</li>
}
And here is the ActionResult I am trying to hit in the SetitngsController controller:
public ActionResult SelectSite(int id, int siteId)
{
//..code here
}
The error occurs thhough, because my URL it outputs is as follows:
~/SettingsController/SelectSite/1?siteId=1
instead of being ~/SettingsController/SelectSite/?id=1&siteId=1344
Am I obvioulsy misunderstanding how to be able to update the current view on the page with a new url and adding params to it this way. Is this wrong in MVC theory, or am I just missing somthing? Thanks in advance!
It is because of your routing table. By default it looks like {Controller}\{Action}\{id}, so your id param is right after action.
You can either change param name or change routing (but the last solution has much more complexity), for example:
#Html.ActionLink(site.Name,
"SelectSite",
"SettingsController",
new { environmentID = Model.EnvironmentID, siteId = site.SiteID}, null)
public ActionResult SelectSite(int environmentID, int siteId)
{
//..code here
}
I am doing my homework in which I am developing a shopping site in asp.net MVC 3 and currently I am doing my work only in views. I have a product page and on the click of details I have to open product detail page.
Details
I have multiple products and I want to tell my product detail page that which product details is opened. One way is this I can append Id with URL like
Details
But I am unable to understand how I can receive this id on the product detail page since I have no controller and no model and I am fetching data using compact database on the .cshtm page using server side code.
You can access the query string using Request.QueryString["key"]. So I suppose you'll want to use something like this:
#{
var myProductId = Request.QueryString["id"];
}
Caveat: Of course this is would be a bad practice, and normally the MVC pattern calls for you to pull the ID in your Controller's action, fetch model data, and return that model data to the View. The View should know as little about things like the Query String, and any program logic, as possible.
public class ProductController : Controller
{
public ActionResult ProductDetails(string id)
{
MyProduct model = SomeDataSource.LoadByID(id);
return View(model);
}
}
You can access it via Request object:
#Request.Params["id"]
Nobody mentioned that you'll probably want to change your link:
Details
to something like:
<a href="#Url.Action("ProductDetails", "Product", new {#id = 1})" >Details</a>
<div class="box-button">#Html.ActionLink("Details", "Course", new { id = item.id }, new { #class = "btn btn-default" })</div>
I want to change:
www.testurl.com/sports/blog/1
Where sports is my area, blog is my action and 1 is an ID of a blog post, to:
www.testurl.com/sports/blog/test-title-of-blog
Where blog is still my action but the id is not shown, but instead the title/permalink of the blog is.
Here is my AreaRegistration for this action:
context.MapRoute(
"sports",
"sports/{action}/{content}",
new { area = "Sports", controller = "Sports", action = "", content = "" });
Here is my action at the moment:
[HttpGet]
public ActionResult Blog(string content)
{
int contentId;
if (Int32.TryParse(content, out contentId))
{
model = service.GetBlogById(contentId);
}
else
{
model = service.GetBlogByTitle(content);
}
//Change URL to be: www.testurl.com/sports/blog/ + model.SEOFriendlyTitle
return View(model);
}
Users are able to search via the ID of the blog, but also by the title of it, but I only want the title to appear in the url bar, never the id.
I cannot do this via Redirect rules due to the continuing maintenance that would cause.
Is the controller the right place to do this? -Remember I may not have my title until after I retrieve it from the database using the ID
How would I go about changing the URL to display the title vs. the ID?
I think what you should do is return a RedirectResult to the new Url if the ID is numeric and is a valid contentId :
int contentId;
if (Int32.TryParse(content, out contentId))
{
model = service.GetBlogById(contentId);
if(model != null)
{
return RedirectResult(/*url using the title*/);
}
}
else
{
model = service.GetBlogByTitle(content);
}
//Change URL to be: www.testurl.com/sports/blog/ + model.SEOFriendlyTitle
return View(model);
Of course, that will cause another round trip to the server but I can see a way to change the browser URL without a page redirect. You should also make sure that all published urls on your site are using the title instead of Id.
I hope it will help.
I suggest giving this a quick read.
http://www.dominicpettifer.co.uk/Blog/34/asp-net-mvc-and-clean-seo-friendly-urls
If you are really can't have the ID in Url and don't want to do redirects then I think storing Url as Slugs in the database is the only other option.
*Some points if you are going to do this.*
Add a Unique Constraint to the column at the Database Level to avoid duplicates.
Create a Database Index on this column to speed up you reads.
So with this Url
www.testurl.com/sports/blog/test-title-of-blog
This is your unique slug that you will query the database for instead of an ID
test-title-of-blog
My story is: I have a couple of forms in separately views that post description info to edit. And every description belongs to different places. So I'm sending also refTypeId info in my forms to decide which description belongs where. So far ok. but I want to return back to edit description view where form was sent from after editing description. So I need to know where form came from that I just edited in my EditDescription action. My EditDescription action method following code:
[Authorize]
[HttpPost]
public ActionResult EditDescription(string descriptionToEdit, int refTypeId)
{
var entity = _entities.Descriptions.Where(e => e.Id == refTypeId).Select(e => e).FirstOrDefault();
entity.Description = descriptionToEdit;
_entities.SaveChanges();
var Description = _entities.Descriptions.Where(e => e.Id == refTypeId).Select(e => e).FirstOrDefault();
ViewData["Description"] = Description.Description;
TempData["Message"]="Description has been saved";
return (?);// i need to know which view that form was sent from
}
send another parameter called ReturnUrl and redirect to it on success.