Send and Receive data in .cshtml page - c#

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>

Related

Execute a controller from view in ASP.NET MVC - Razor

I am trying to print the name of the user who executes my web app. It is written in MVC-Razor.
From the initial View, I would to execute the controller below:
[Authorize]
public ActionResult Check()
{
var check = new CheckAD();
var user = new User {Name = check.CheckSecurityWithAD()};
if (!string.IsNullOrEmpty(user.Name))
{
return View("Checked", user);
}
var errors = new ErrorsModel()
{
Messages = new List<string>(){"You don't have permission"}
};
return View("Error", errors);
}
This controller returns another view if the user is correctly authenticated:
#model UsersActivationWeb.Models.User
#{
ViewBag.Title = "Checked";
}
#{ <p> Logged come #Model.Name </p>};
How can I print the second view (I think it's a partial view) in the first one using the controller?
Thanks
Sounds to me like you need an Html.Action. This will run the controller code and display the view contents that are produced where you place the call.
Most likely you will need this overload, Html.Action(string actionName, string controllerName).
Assuming the controller is called CheckController. In your initial view call it like this
#Html.Action("Check","Check")
Since you don't want people navigating to the Check view you should give it a ChildActionOnly attribute so it looks like this
[Authorize]
[ChildActionOnly]
public ActionResult Check()
{
//rest of code
}
Finally you almost certainly don't want the layout contents to appear with the Checked view so change your Checked view to this
#model UsersActivationWeb.Models.User
#{
Layout = null;
}
#{ <p> Logged come #Model.Name </p>};
Since you are doing authorization logic in the Check action you might not need the Authorize attribute. I say that because with it a user not logged in will not get the error or their name. Maybe you want this though, I'd need to know more about your code to say for sure.
This way you will either get the name of the user or the errors as required.

ViewDataDictionary vs anonymous object in ASP.net MVC 5

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.

How to access a UserID when a hyperlink is selected

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.

MVC Maintaining Model through multi view form submits

So I am working on a MVC which is basically three steps.
Create a view for each step i.e.
StepOne
StepTwo
StepThree
On step one and two I ask the users to enter some details.
All the values for the multiple step I store in one Model.
And getting from StepOne to StepTwo is fine. Certain values in my model are being set and maintained.
But on StepTwo when I do my second httppost and pass the model, it seems to just create a new instance of the model and values from stepone are not maintained.
<% using (Html.BeginForm("StepTwo", "Home", FormMethod.Post, new { id = "restrictionForm" })) { %>
<%: Html.AntiForgeryToken() %>
<div id="wrapping" class="clearfix">
<h3>Postcode Restriction Type : </h3>
<%= Html.DropDownListFor(x => x.SelectedRestriction, Model.RestrictionTypes,"Select Restriction...", new { #class = "selmenu required" }) %>
<h3>Restriction Description : </h3>
<%= Html.TextBoxFor(m => m.RestrictionDescription, new { #class = "txtblock required" }) %>
</div>
<section id="buttons">
<input type="submit" value="Submit" id="submitBtn" />
</section>
And in my controller
On Page Load my Model is still intact and still maintains values from previous step.
[Authorize]
public ActionResult StepTwo(PostcodesModel model)
{
var summaryMessage = "";
model.SummaryMessage = summaryMessage;
model.RestrictionTypes = _Provider.GetRestrictionTypes();
return View(model);
}
But at the Httppost, the model has lost values and seems to have created new instance of model.
[Authorize]
[HttpPost]
[ActionName("StepTwo")]
[ValidateAntiForgeryToken]
public ActionResult StepTwoPost(PostcodesModel model)
{
return View(model);
}
Any idea how I can maintain model between Http Posts ?
It seems from your question that you believe models persist across requests. This is not true.
You either pass information to the view via your model from the controller, or submit values from your view to your controller and MVC handles this by binding html form inputs to your View Model.
If you want to persist your View Model across each step you need to take the values accepted and copy them into a new model (or directly inject it) when calling your new view.
Something like this (I just typed this up off my head so its not clean but should give you an idea):
[HttpGet]
public ActionResult StepOne()
{
var model = new MyNewModel();
return View(model);
}
/* NOTE THE MODEL PASSED BACK HERE IS NOT THE EXACT SAME OBJECT
AS THE ONE CREATED IN THE GET ACTION ABOVE, MODEL BINDING HAS OCCURRED
TO READ YOUR FORM INPUTS AND MATCH THEM TO A NEW MODEL WHICH IS EXPECTED */
[HttpPost]
public ActionResult StepOne(MyNewModel model)
{
if (ModelState.IsValid)
{
// Do something here
// pass model to new view
TempData["model"] = model;
return RedirectToAction("StepTwo");
}
return View(model);
}
[HttpGet]
public ActionResult StepTwo()
{
MyNewModel model;
if (TempData["model"] != null)
{
model = (MyNewModel) TempData["model"];
// make some changes if necessary
model.MyProperty = 2;
return View(model);
}
return RedirectToAction("StepOne");
}
I think you can also keep your model in Session ( per application ) or in a ViewState ( per page ).
Every time you make a post you upgrade the session. It's also optimal because on the client side you receive only a session identifier.
Some differences between Session and Viewstate:
Session is per application, while ViewState is per page
Session sends to the client side only a session identifier, while ViewState sends an ecrypted text

Transfer Model Data in View to the Controller

I have a model that I am using in my view that is full of data. This data is then edited in the view. I need to figure out a way to resubmit this data back over to the controller.
Here is what I have so far.
VIEW:
#using (Html.BeginForm("DownloadCSV", "Respondents", FormMethod.Post))
{
#Html.HiddenFor(m => m.FilterSet)
<div class="btn btn-default pull-right" id="dispoCSV" onclick="$('#csvFormSubmit').click()">
<i class="icon-file-alt"></i> Disposition Report
</div>
<input id="csvFormSubmit" type="submit" style="display:none;" />
}
CONTROLLER:
[HttpPost]
public ActionResult DownloadCSV(RespondentsFilterSet model)
{
string csv = "Charlie, Test";
return File(new System.Text.UTF8Encoding().GetBytes(csv), "text/csv", "DispositionReport.csv");
}
MODEL:
public class RespondentsFilterSet : ColdListFilterSet
{
public List<int> OwningRecruiters { get; set; }
public List<int> RecruitingGroups { get; set; }
public override bool HasAtLeastOneFilter()
{
return base.HasAtLeastOneFilter() || OwningRecruiters.IsNotNullOrEmpty() || RecruitingGroups.IsNotNullOrEmpty();
}
public override ExpressionBase ToExpression()
{
var expr = base.ToExpression();
var expressions = expr == null ? new List<ExpressionBase>() : new List<ExpressionBase> { expr };
if (OwningRecruiters.IsNotNullOrEmpty())
{
expressions.Add(new InExpression<int> { Field = Create.Name<Respondent>(r => r.RecruitedBy), Values = OwningRecruiters });
}
if (RecruitingGroups.IsNotNullOrEmpty())
{
expressions.Add(new InExpression<int> { Field = Create.Name<Respondent>(r => r.RecruitingGroupId), Values = RecruitingGroups });
}
return expressions.Count == 0 ? null : BuildAndExpressionFromList(expressions);
}
}
I realize that my controller is not not finalized. I just have displaying some static csv. But I can't figure out why my model from my view is always null when returned to the controller.
Just look at your form. There's not a single input element (except the submit button). You cannot expect to get anything back on the server in this case.
Please read about HTML and how forms work in HTML. In HTML forms you have input fields. Things like text fields, hidden fields, checkboxes, radio buttons, ... - fields that the user interacts with get submitted to the server.
The fact that you have made your HttpPost controller action take some model as parameter doesn't mean at all that this parameter will be initialized. In ASP.NET MVC you have a default model binder. This model binder looks at what gets sent to the server as values when the form is submitted and uses the names of the fields to bind to the corresponding properties. Without input fields in the form, nothing gets sent to the server. Just use the debugging tools built into your web browser to inspect what exactly gets sent to the server.
Contrary to classic ASP.NET WebForms, ASP.NET MVC is stateless. There's no ViewState to remember your model.
So all this rambling is to say that you should read more about HTML forms first and understand the stateless nature of the web before getting into ASP.NET MVC. As far as your particular problem is concerned, well, assuming the user is not supposed to modify any values of the view model in your view throughout some input fields, you could simply include a hidden field containing the id of your model in the form. This id will then be sent to your POST controller action as parameter and you could use it to retrieve your original model from wherever it is stored (I guess a database or something).

Categories