Razor syntax to complete an MVC form - c#

I'm very new to using Razor with C# and am conducting this project in order to try to better my understanding of it.
This application is supposed to, once completed, is ask the user to input three integers and then print out the sum of those integers. Right now, I have the basic frame of the View and Controller set up. (There is currently no Model.) The controller is set up to use an HTTP-Post protocol in order to send information to the HTML form.
What I'm struggling with, is the code needed to communicate the data directly to the form, as well as whatever parameters are needed so that ASP.net will ignore the presence of two identically-named controller actions (which I'm told it should be able to do once the Razor syntax is set up properly).
Any guidance here would be very helpful. (Note: It is a requirement that I use the HTTP Post protocol in the finished solution.)
Controller:
public ActionResult Index(int firstInt = 0, int secondInt = 0, int thirdInt = 0)
{
return View();
}
[HttpPost]
public ActionResult Index(int firstInt = 0, int secondInt = 0, int thirdInt = 0)
{
int sum = firstInt + secondInt + thirdInt;
ViewBag.result = sum;
}
Index View:
<form action="" method="post">
<table>
<tr><td>Enter the 1st Number: <input id="firstInt" name="firstInt" type="text" value="0" /></td></tr>
<tr><td>Enter the 2nd Number: <input id="secondInt" name="secondInt" type="text" value="0" /></td></tr>
<tr><td>Enter the 3rd Number: <input id="thirdInt" name="thirdInt" type="text" value="0" /></td></tr>
<tr>
<td><input id="Submit" type="submit" value="submit" /><input id="Reset" type="reset" value="reset" /></td>
</tr>
<tr>
<td>Sum = #ViewBag.result</td>
</tr>
</table>
</form>

You need to make sure your methods with same name has unique signature. Since you mentioned the user enter the numbers via the form, there is no reason to have those params in the GET action method. Just remove it and it should work now.
public ActionResult Index()
{
return View();
}
Also you need a return View(); statement in your HttpPost action. Otherwise you will get a compilation error.
[HttpPost]
public ActionResult Index(int firstInt = 0, int secondInt = 0, int thirdInt = 0)
{
int sum = firstInt + secondInt + thirdInt;
ViewBag.result = sum;
return View();
}
If you are going to have many parameter values coming from the form, i would advise creating a view model which has those properties and use that as the parameter.

Normally what you do for Razor views is declare the Model, and use the Razor methods to output the form and form elements. As Shyju says, you need unique signatures on the actions.
#using MyModelNamespace
#model MyModel
#using (Html.BeginForm("Index", "HomeController", routevalues, etc..) {
Html.TextBoxFor(m => m.firstInt);
}
Your post action should take the model as a parameter
public ActionResult Index() {
return View();
}
[HttpPost]
public ActionResult Index(MyModel m) {
int sum = m.firstInt + m.secondInt + m.thirdInt;
ViewBag.result = sum;
return View(m);
}
You can set ViewBag state in your action.

Related

Send Selected DropDownList value to HomeController ActionResult

Hi I have a drop down list that is filled in from comma delimited values in the config. This works fine.
What I am trying to do is to send the selected value on button click to a ActionResult in the HomeController.
I created a Model, which is taking a string. When I hit the button I get error:
The view 'TestAction' or its master was not found or no view engine supports the searched locations.
This is what my Controller looks like:
[HttpPost]
[ActionName("TestAction")]
public ActionResult TestAction(SQL_Blocks_App.Models.DropdownList SelectedValue)
{
//System.Diagnostics.Debug.WriteLine(SelectedValue);
return View();
}
This is what my model looks like:
public class DropdownList
{
//
// GET: /DropdownList/
[Display(Name = "Servers")]
public string SelectedValue{ get; set; }
}
and this is what my Index View looks like:
<form id="SelectedValue" action="/Home/TestAction" method="post" style="margin: 0">
<div class="col-lg-5">
#{
ViewBag.Title = "Index";
}
#Html.DropDownList("YourElementName", (IEnumerable<SelectListItem>)ViewBag.DropdownVals, "--Choose Your Value--", new
{
//size = "5",
style = "width: 600px"
})
</div>
<div class="col-lg-5">
<input type="submit" value="Run Query" />
<input id="Button2" type="button" value="Clear" onclick="window.location.reload()" />
</div>
</form>
I want to clarify. My end goal is to use the selected value in a SQL query in the ActionResult and return the results back to the index so I can fill them in a table. ( You don't have to show me how to do the SQL part for now I just would like to see the selected value at least printed in the output.)
Redirect to index action, and pass the parameters along
[HttpPost]
[ActionName("TestAction")]
public ActionResult TestAction(SQL_Blocks_App.Models.DropdownList _selectedValue)
{
//System.Diagnostics.Debug.WriteLine(SelectedValue);
return RedirectToAction("Index", "[Controller]", new {#_selectedValue = _selectedValue });
}
and then your Index method should accept the parameter.
[HttpGet]
public ActionResult Index(SQL_Blocks_App.Models.DropdownList _selectedValue)
{
//use _selectedValue
}
I would recommend using another method other than your index, or make Dropdownlist nullable/set a default for it.
The default framework behavior of return View() is to return a view with the same name as the currently-executing action. Which is TestAction. The error is telling you that no such view was found.
You have a couple of options. You can either create the view, or you can return something else. For example, if you want to redirect back to the Index then you can return a redirect result:
return RedirectToAction("Index");
You could also specify the Index view in the response:
return View("Index");
However, keep in mind that the URL will still be for TestAction and not for Index, which could result in unexpected changes to behavior if you're not aware of this.
Edit: Based on comments on this answer, it sounds like what you actually want is to build a pair of actions which generally operate on the same view. This isn't particularly common for an index view, but is very common for edit views. The only difference is semantics, structurally the concept works anywhere.
Consider two actions:
public ActionResult Index()
{
// just show the page
return View();
}
[HttpPost]
public ActionResult Index(SQL_Blocks_App.Models.DropdownList SelectedValue)
{
// receive data from the page
// perform some operation
// and show the page again
return View();
}
Requests between these two actions would differ only by the HTTP verb (GET or POST), not by the action name on the URL. That name would always be "Index". But when the form on the index view is submitted via POST and has a "SelectedValue", the second action is invoked instead of the first.
In that second action you would perform your database interaction, gather whatever data you needed, and if necessary include a model or some additional data in the response.
You TestAction method is returning to a View. Make sure View TestAction.cshtml exists and is in the Home folder.

Passing whole model to controller from view via link

I want to pass an entire model to the controller. Right now it passes nothing and I don't know why. The Model is partially filled in when it get's to this page, so it should atleast have some info in it.
The problem: When I click on the button on the view, the model is not passed to the controller. Not even the filled in parts!
View (that contains a model that is partially filled in)
#{
ViewBag.Title = "Winkelmand";
Layout = "~/Views/Shared/_Layout3.cshtml";
}
#model IntroSport.Models.Bestel
<br />
<br />
#if (Model.winkelmand.facturen != null)
{
<table style=" width:auto; height:auto; border-style:solid; border-color:black;">
<tr><th>Artikelnummer</th><th>Merk</th><th>Naam</th><th>Prijs</th><th>Aantal</th></tr>
#for (int i = 0; i < Model.winkelmand.facturen.Count; i++)
{
<tr>
<td>#Model.winkelmand.facturen[i].product.ProductID</td>
<td>#Model.winkelmand.facturen[i].product.Merk</td>
<td>#Model.winkelmand.facturen[i].product.Naam</td>
<td>€#Model.winkelmand.facturen[i].product.Prijs</td>
<td >#Model.winkelmand.facturen[i].Aantal</td>
</tr>
}
</table>
}
<br />
<hr />
<b>Totaal: </b>€ #Model.winkelmand.Totale_prijs
Bestel!
Controller:
public ActionResult KlantOverzicht(Bestel bestel)
{
return View(bestel);
}
You would not be able to simply provide the whole model into the #Url.Action and have it create the link with each of the fields in your model.
You essentially will need to create the link "by hand"!
From the view that you have, it appears the user is not changing any information, and most likely, you pulled the information you are displaying from a database, so if you do create the link that passes in the model, the information will match the data in your database.
My suggestion would be that instead of posting an unchanged model to the server, you simply pass in the Id of the object into your view and have the view retrieve the object from the database.
Bestel!
You can send Model to controller with <form>.
Or send all properties by link and in action collect them to a new model.
<a href="#Url.Action("Klantoverzicht", "Winkelmand",
new {
pId = Model.ProductID,
mark = Model.Merk,
name = Model.Naam,
price = Model.Prijs,
number = Model.Aantal,
})">Bestel!</a>
In action:
public ActionResult KlantOverzicht(int pId, string mrk, string nam, double price, int number )
{
Bestel model = new Bestel();
model.ProductID = pId;
model.Merk = mark;
model.Naam = name;
model.Prijs = price;
model.Aantal = number;
}

html actionLink parameters to view

I'm a noob in .Net and all the web developpement :s
I'm having an issue using html.BeginForm and html.ActionLink.
I got this in my homeWeb.cshtml:
#using (Html.BeginForm("resultWeb", "Result", new { val = 1 }, FormMethod.Post ))
{
<div class="main-block">
<input style="width:100%;" type="text" name="searchValue" /><br />
<div style="text-align: center;">
<input type="submit" value="Submit" />
</div>
</div>
}
its calling my result controller and my resultWeb view sending the val = 1 as parameter
here is my ResultController.cs:
[HttpPost]
public ActionResult resultWeb(int val, FormCollection collection)
{
List<WebSite> list = new List<WebSite>();
// Doing stuff with my list and the val
return View(list);
}
this part is working and well sending the parameter to my view.
The problem is when i try to do the same thing with an html.ActionLink on an other page
resultWeb.cshtml:
<tr>
#for (int i = 0; i <= Model.Count / 15; i++)
{
int j = i + 1;
<td>#Html.ActionLink(#j.ToString(), "resultWeb", new { val = j })</td>
}
</tr>
And when i click on one of the links, it doesn't work i got this error:
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Result/resultWeb/1
I guess i'm doing something wrong but i don't understand what. Does someone can help me on this ?
Thanks !
Actionlinks can't post a form/data to a controller. All they do is create <a> tags.
If you want to submit the form with an actionlink, you could use the #Ajax.ActionLinkhelper, or just post the form with jquery alltogether.
Also, this question has been asked lots of times before on stackoverflow, like here or here.
Thousands Answer is correct you cannot Post data via ActionLinks. If your FormsCollection is not too large then you can use Query Strings.
This is what I have done
Controller:
public ActionResult Index(string loc, string ma, string mo, int co = 0, int mi = 0)
{
search c = new search() { loc = loc, ma = ma, co = co, mo = mo, mi = mi }
/*replace search() and query string variables with your FormsCollection*/
/*Do thing here*/
return View(DisplayModel)
}
MyModels
public class DisplayModel
{
public search Search { get; set; }
public List<Website> Result { get; set; }
}
public class Search
{... All my search variables in this model}
And finally the View
#model MyApp.Models.DisplayModel
<div>
#using (Html.BeginForm("Index", "Buying", FormMethod.Get)){
<fieldset>
<legend>My form</legend>
<input id="ma" name="ma" type="hidden" disabled="disabled" value="#Model.Search.ma" />
... The way you choose to display your your view. You can either keep the same form hidden or
<input type="submit" value="mybutton"/>>
</fieldset></div>
#foreach( var item in Model.Result)
{
... The way you choose to display your List.
}

FormCollection not populating

I'm working on an MVC project which I want to pass a FormCollection, populated with form data, and post it to my action method in my controller. Here's an example of the view:
<asp:TextBox ID="txtClientLastName" name="txtClientLastName" runat="server" class="focus"/>
(Yes, I know! ASP controls in an MVC view isn't good but that's what I have. There's back end code in the view between tags as well which is why I haven't replaced them)
I've used a helper to link to my action:
<%=Html.ActionLink("Save","ClientInformationEdit",new {id=Model.PersonId})%
which calls my action:
public ActionResult ClientInformationEdit(int id, FormCollection form)
{
//rptLOA_GridCommands(form, id);
CIHelper ch = new CIHelper();
ch.person.LastName = form["txtClientLastName"];
db.SaveChanges();
return View(ch);
}
My ìdpasses the correct value but FormCollection form is null so form["txtClientLastName"] is null and I dont know why.
Add post attribute like below:
[HttpPost]
public ActionResult ClientInformationEdit(int id, FormCollection form)
{
//rptLOA_GridCommands(form, id);
CIHelper ch = new CIHelper();
ch.person.LastName = form["txtClientLastName"];
db.SaveChanges();
return View(ch);
}
If you want to post form on click of hyperlink then add following code:
<%=Html.ActionLink("Save","ClientInformationEdit",new {id=Model.PersonId,onclick="document.getElementById('form-id').submit();"})%>
try this:
#using (Html.BeginForm("Save", "ClientInformationEdit", FormMethod.Post))
{
<input type="hidden" value="#Model.PersonId"/>
<asp:TextBox ID="txtClientLastName" name="txtClientLastName" runat="server" class="focus"/>
<input type ="submit"/>
}
in your view

Load View again by passing updated parameter to the same Controller MVC 3

I want to load the same view again by passing updated parameter from text input on the link click. I tried to use something like <a href="#Url.Action("Index", "Home", new {id = "txtCount".value }). Not sure if there is even a way to do this. I know I could use partial but I want to reload the whole page with updated parameter. Thanks in advance for any help.
Controller
[HttpGet]
public ActionResult Index(int id)
{
return View(id);
}
View
#model int
#using (#Html.BeginForm())
{
<input id="txtCount" value="1" />
Update
for (int i = 0; i < Model; i++)
{
<div>#i </div>
}
}
Maybe something like this
Go!
and binding with jquery
$("#mylink").click(function(){
document.location.href = '#Url.Content("~/Controller/Action")' + $("#mytxt").val();
return false;
});
Obviously with the proper validations if the textbox is empty and all that stuff.
You cannot add the id value to the #Url.Action because it is processed before on the server side, before the page is rendered

Categories