Having trouble in accessing posted form data (MVC) - c#

How to access posted form data in action method and display in view
I'm creating an input wizard in MVC. There are two views, one for taking input from user and another for display the input data.
Here is the model's code:
public class Info
{
public int CustomerId { set; get; }
public double Price { set; get; }
public string name { set; get; }
}
}
Controller's Code-
public ActionResult FillCustomer()
{
return View();
}
public ActionResult DisplayCustomer(FormCollection frm)
{
Info info = new Info();
info.name = Convert.ToString( Request.Form["name"]);
info.Price = Convert.ToDouble(Request.Form["price"]);
info.CustomerId = Convert.ToInt32(Request.Form["customerid"]);
return View(info);
}
FillCustomer View's Code-
<form method="post" action="DisplayCustomer">
Name: <input type="text" id="name" /><br />
Price: <input type="text" id="price" /><br />
CustomerId: <input type="text" id="customerid" />
<br />
<input type="submit" id="btn1" />
</form>
</body>
</html>
DisplayCustomer View's Code-
<body>
<div>
Name is <%=Model.name %> and ID is <%=Model.CustomerId %>
<%if (Model.Price > 200)
{%>
Greater than 200
<%}
else %>
<%{%>Lesser than 200
<%} %>
</div>
</body>
</html>
I checked with debugger, controller is not getting posted data.

Your form's input elements should have a name attribute
<form method="post" action="DisplayCustomer">
Name: <input type="text" id="name" name="name" /><br />
Price: <input type="text" id="price" name="price" /><br />
CustomerId: <input type="text" id="customerid" name="customerid" />
<br />
<input type="submit" id="btn1" />
</form>
Now you will get form data as
Info info = new Info();
info.name = Convert.ToString( Request.Form["name"]);
info.Price = Convert.ToDouble(Request.Form["price"]);
info.CustomerId = Convert.ToInt32(Request.Form["customerid"]);
In controller, form data is received as key/value pairs. And keys are generaetd from name attributes.

You are using MVC so the parameter in DisplayCustomer method is your model passed from view, which is created implicitly by model binder. Change the type from FormCollection to Info class as following:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult DisplayCustomer(Info model)
{
// you can now access to Info properties
}
This way values of Info object are populeted and I think this is what you are trying to accomplish.

I think you have missed to write a Attribute top of the DisplayCustomer function. Just write it, I hope it will work.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult DisplayCustomer(FormCollection frm)
{
Info info = new Info();
info.name = Convert.ToString( Request.Form["name"]);
info.Price = Convert.ToDouble(Request.Form["price"]);
info.CustomerId = Convert.ToInt32(Request.Form["customerid"]);
return View(info);
}

Related

URL Redirect to Variable

I am working on a method that will apply to 2 different views "/DogProfile" and "/DogProfile/Profile" I want to call this method and then have it return to the current page, as it does now for "DogProfile". However, I am having trouble identifying how to create a variable that would store the url of the page I am operating from. i.e. now if I were on the Profile view and run the page I am redirected to the "/DogProfile" page instead of back to the "DogProfile/Profile" page.
Dog Profile Controller:
public IActionResult CheckOut(string activity, int dogID)
{
var status = context.Dogs.Find(dogID);
status.CheckedOut = true;
status.Activity = activity;
status.TimeCheckOut = DateTime.Now;
context.SaveChanges();
return Redirect("/dogprofile");
}
Profile view:
#model WebApplication2.Models.Dog;
<h1>#Model.DogName</h1>
<img src="#Model.ImageSource" class="dogProfile"><img />
<br />
<br />
#if (Model.Description != null)
{
<h2>Dog Special Requirements:</h2>
<p>#Model.Description</p>
}
<form asp-controller="DogProfile" asp-action="CheckOut" method="post">
<select name="activity" id="activity">
<option value="walk">Walk</option>
<option value="furlough">Furlough</option>
<option value="bathe">Bathe</option>
</select>
<br />
<input type="submit" value="Check Out" />
<input type="hidden" name="dogID" value="#Model.Id" />
</form>
If you want to submit via the Profile page and return to the current "DogProfile/Profile" page instead of the "/DogProfile" page, you can try the following code.
[HttpPost]
public IActionResult CheckOut(string activity, int dogID)
{
var status = _context.Dogs.Find(dogID);
status.CheckedOut = true;
status.Activity = activity;
status.TimeCheckOut = DateTime.Now;
_context.SaveChanges();
return Redirect("/dogprofile/profile" + "/" + dogID);
}

Knowing the values of check box in the controller with razor

I have a asp.net mvc application with razor engine.
In a view Home i have this snippet:
<section id="form_admin">
<form action="/Super/Manipuler" method="post">
<fieldset>
<legend>Formulaire d'ajout d'un administrateur</legend>
#Html.Label("Login")
#Html.Label("Mail")
#Html.Label("Password")
#Html.Label("Name")
<br />
<br />
#if(Model != null){
foreach (Upload.Models.AdminModels admin in Model)
{
if (i == 0){
<input type="radio" checked class="radio" name="radio" value="#admin.Login" >
}
else{
<input type="radio" class="radio" name="radio" value="#admin.Login" style="margin-left:0.3px;">
}
<label id="log">#admin.Login</label>
<label id="logm">#admin.Mail</label>
<label id="logp">#admin.Password</label>
<label id="logn">#admin.Name</label>
<br />
i++;
}
}
<br />
<input type="submit" value="Editer" name="submit_button"/>
<input type="submit" value="Supprimer" name="submit_button" />
Créer un nouveau compte
</fieldset>
</form>
</section>
In the controller : the action Manipuler is the below:
public ActionResult Manipuler()
{
string buttonName = Request.Form["submit_button"];
string _login = Request.Params["radio"];
Upload.Models.AdminModels admin = new AdminModels();
Upload.Models.CompteModels.Modifiying_login = _login;
if (buttonName == "Editer") { return RedirectToAction("Edit", "Admin"); }
else { admin.Delete_admin(_login); return RedirectToAction("Home", "Super"); }
}
It's works fine but i'd like to change the radiobox to checkbox.
My question is how to know all checked box in the collection of checkbox in the action Manipuler ?
Take a look at Phil Haack's article on model binding a checkbox list. Basically, you just need to set up the HTML in a specific way (name your checkboxes the same which will then convert the various POSTed values into a list).
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

How to bind OrderedDictionary?

I try to bind an OrderedDictionary to a view but when the post method gets invoked the Dictionary is always empty.
Here is my code:
[HttpGet]
public ViewResult Edit(string username, string password)
{
Xml test = new Xml(#"c:\Users\pc\Desktop\xml - Copy.xml");
XmlNode userNode = test.GetUserNodeByUsernameAndPassword(username, password);
User user = new User();
user.BindData(userNode);
return View(user.user);
}
[HttpPost]
public ViewResult Edit(OrderedDictionary attributes)
{
return View(attributes);
}
And here is the view:
#using (Html.BeginForm("Edit", "Users")) {
#Html.ValidationSummary(true)
<fieldset>
<legend>User</legend>
<p>
<input type="submit" value="Save" />
</p>
#{int counter = 0;}
#{string name = "";}
#foreach (DictionaryEntry attribute in Model)
{
{ name = "[" + counter + "].key"; }
<input type="hidden" name=#name value=#attribute.Key />
#attribute.Key #Html.TextBoxFor(m => attribute.Value)
counter++;
<br />
}
</fieldset>
}
And the result Html looks like this is:
<input type="hidden" value="Username" name="[0].key">
Username
<input id="attribute_Value" type="text" value="Anamana" name="attribute.Value">
So the content of the OrderedDictionary appears fine in the view but when I make a post back the binding isn't working and the directory remains empty.
Concept
To bind a dictionary you have to change the name attribute in the html input tag. Something like this:
In your controller:
[HttpPost]
public ActionResult Edit(IDictionary<string, string> attributes)
{
}
In your HTML:
<input type="text" name="attributes[0].Key" value="A Key" />
<input type="text" name="attributes[0].Value" value="A Value" />
<input type="text" name="attributes[1].Key" value="B Key" />
<input type="text" name="attributes[1].Value" value="B Value" />
The attributes name should be before the index [0] on ther name attribute, because your action expect it.
Tips
I would use the HiddenFor and TextBoxFor HTML Helper of the Asp.Net MVC.
#Html.HiddenFor(model => model[i].Key)
#Html.TextBoxFor(model => model[i].Value)
And it will render in the format that the asp.net mvc will understand and get it working.
For more samples about databind take a look at this link.
Meantime I have found the solution.
I can pass an OrderedDictionary to the view page.
It process it by the following Razor code:
#model System.Collections.Specialized.OrderedDictionary
(...)
#{int counter = 0;}
#{string name = "";}
#foreach (DictionaryEntry attribute in Model)
{
{ name = "[" + counter + "].key"; }
#Html.Hidden(name, attribute.Key)
{name = "[" + counter + "].value";}
#attribute.Key #Html.TextBox(name, attribute.Value)
counter++;
<br />
}
The result HTML's structure fits to the samples which is found in a book, the values from the dictionary appears fine on the page.
After POST was invoked the POST handler function gets the modified values in a Dictionary.
[HttpPost]
public ViewResult Edit(Dictionary<string, string> attributes)
{}
I don't know why but I can't use OrderedDictionary here.

Get html items from view to control

Still kind of new to MVC, so please bear with me. I'm trying to grab some dynamically generated HTML. In this case, list items in my notifyList. I plan on looping through each one in the controller and adding them as database entries. Any help is appreciated, thanks.
View
#model _BaseViewModel
// The form it's within...
#using (Html.BeginForm("Create", "Leaf", FormMethod.Post, new { id = "createForm" }))
<div class="editor-label bottom-area bottom-header">
Notification List:
</div>
<div class="editor-field bottom-area">
<ul id="notifyList"></ul>
</div>
Controller:
[HttpPost]
public ActionResult Create(_BaseViewModel model)
{
// Some loop here
// get html here
db.UserItems.AddObject(model.user);
db.SaveChanges();
//
return RedirectToAction("Index");
}
As far as I understood, you use jQuery to fetch <li/> elements into notifyList. What you need to do here is to generate a hidden input as well. Sample:
$("#btnAppend").click(function() {
for(var i = 0; i < 4; i++) {
var _val = "Foo " + i;
var $li = $("<li/>").text(_val);
var $hidden = #("<input/>").
attr("type", "hidden")
attr("name", "foo").
val(_val);
$hidden.appendTo($li);
$li.appendTo("#notifyList");
}
});
This code will generate following output inside your DOM:
<ul id="notifyList">
<li>Foo 0<input type="hidden" value="Foo 0" name="foo" /></li>
<li>Foo 1<input type="hidden" value="Foo 1" name="foo" /></li>
<li>Foo 2<input type="hidden" value="Foo 2" name="foo" /></li>
<li>Foo 3<input type="hidden" value="Foo 3" name="foo" /></li>
</ul>
When you make a http form post, you can grab the values by the below controller action implementation:
public ActionResult Index(string[] foo) {
foreach(var item in foo) {
//Work with each individual item
}
//continue your code
}
it doesn't work this way. html only exists in the view. the controller has no concept of html (not should it). data sent to the controller comes in 1 of types (GET, POST). there are others, but these are the main to.
get is typically associated with the querystring www.domain.com/mypage.aspx?key=value
where post is the input values from form
<form action="mypage.aspx" method="post">
<input name="key" value="value"/>
<input type="submit" value="click me"/>
</form>
So adding items to a html list won't provide any meaning to the controller. javascript and ajax provide more options on how the data gets sent to the server, but the data is sent, not the markup. and the data is sent as key value pairs.

calculate button pressed - retrieve rates from database

I need to link to the database (finance rates) when someone enters a number in the text box and clicks calculate that it will pull the rates from the database and display the calculation below in a 'form message'. What should I put in the homecontroller/index to link the code to the database?
Index.aspx:
<td>You wish to convert:
<input type="text" name="amount" size="30" onblur="test_ifinteger(Index.amount,'amounts')"/>
<input type="submit" name="submitter" value="calculate" />
<tr><td colspan="2">That will produce:<%=ViewData["formmessage"] %></td></tr>
Home Controller:
public ActionResult Index()
{
financeInit();
if (Request.Params["submitter"] == "calculate")
calculatepressed();
return View();
public void calculatepressed()
{
.............
}
I would wrap your fields in a form like this:
<form action="Home" method="get">
<div>
You wish to convert:
<input type="text" name="amount" size="30" id="userValue" onblur=""test_ifinteger(Index.amount,'amounts')"/>
<input type="submit" name="userSubmit" />
<br />
That will produce:<%=ViewData["formmessage"] %>
</div>
</form>
Then have your controller something like this:
public ActionResult Index()
{
int value;
if (int.TryParse(Request.Params["amount"], out value))
{
ViewData["formmessage"] = calculatepressed(value);
}
return View();
}
private string calculatepressed(int value)
{
// Do your magic here and return the value you calculate
return value.ToString();
}
If this ever expands from a simple page you might want to consider changing the form action to a post and having two different methods handling the initial view of the home page and the a view for the results of the calculation.

Categories

Resources