Posting a model back to controller in ASP.NET MVC3 - c#

I'm trying to post a model back to the controller but for some reason the controller always gets NULL back. I know I'm doing something really obviously wrong. What is it?
However if I post back a specific attribute from that model, it works just fine.
Controller:
[HttpPost]
public void MyAction(Company company)
{
System.Diagnostics.Debug.WriteLine("STUFF:" + company.dbName);
if(company.CompanyOptions!=null)foreach (var item in company.CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList) System.Diagnostics.Debug.WriteLine("STUFF:" + item);
else System.Diagnostics.Debug.WriteLine("STUFF IS NULL");
}
View:
#model Domain.Entities.Company
#using (Html.BeginForm("MyAction", "Controller", FormMethod.Post))
{
foreach (var licensedFeature in Model.CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList)
{
#Html.CheckBox(licensedFeature.LicenseName, licensedFeature.IsLicensed, checkboxHtmlAttributes);
#licensedFeature.LicenseName
}
<input type="hidden" name="company" value="#Model"/>
<input id="submit_licenses" type="submit" style="display:none;" />
}

#Model appears to be a complex type so you cannot assign to as the value of the input field.
The best you can do is use an #Html.EditorFor to generate the required html fields for the model and this will ensure that they are posted back as the Company object.
Replace this
<input type="hidden" name="company" value="#Model"/>
with
#Html.EditorFor(model => model)

Related

How do you pass post form variables in ASP.NET C#/Razor?

I'm new to C#/Razor and don't know how to pass form data using the post method. Here's what I've tried:
In login.cshtml:
string username = Request.Form["username"];
string password = Request.Form["password"];
And
string username = Request.Form.Get("username");
string password = Request.Form.Get("password");
In _AppStart.cshtml, I tried:
AppState["username"] = HttpContext.Current.Request.Form["username"];
AppState["password"] = HttpContext.Current.Request.Form["password"];
All return nothing.
Here's the form elements in login.cshtml:
<form action="index.cshtml" method="post" data-ajax="false">
<input type="text" name="username" placeholder="Username">
<input type="password" name="password" placeholder="Password">
<button type="submit">Login</button>
</form>
If you need to pass data between MVC controller and View then you have to let Asp know which action an controller to call.
To accomplish this you could use something like BeginForms in razor an specify the needed information.
This would look like this:
#Html.BeginForm("YourAction", "YourController", FormMethod.Post){
#Html.TextBoxFor(employee => employee.FirstName);
#Html.TextBoxFor(employee => employee.LastName);
#Html.TextBoxFor(employee => employee.Age);
<input type="submit" value="Edit" />
}
Following this snippet you can see that you need A Controller and you name an ActionResult according to the name given here furthermore you can specify if you want to have the action only when posting or only for get forms
An possibile exemple could be the edit like the following code
[HttpPost]
public ActionResult YourAction(Employee emp)
{
if (ModelState.IsValid)
{
// do smth.
}
return View("Name Of the view");
}
Note you need to define this in your Controller and that the Attribute HttpPost lets Asp know that this is a post only ActionResult. This means that only post requests can use this Method. Furthermore
if you wish to have both get and post requests available for this ActionResult then you can simply delete the Attribute then per default it will be available in get and set requests.
You could look at this forum
entry
in Input Type "submit add formaction="ActionMethodName"
#using (Html.BeginForm("MethodName", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="postedFile"/>
<input type="submit" **formaction="UploadData"** value="UploadData"/>
}

How do i send data to asp.net controller so that it can return a view?

What I want to do is so simple, I'm still trying to learn ASP.NET with c# and MVC application but I'm just having a lot of difficulty getting a simple example to go through, then I can grow from it, here's how it goes: I have a simple html5 form that's method is GET, the type is text and I basically want to submit a text into my mvc controller, once my controller get's it, I want it to output that string 'worked' through HTML5, how do I do this?
summary: string 'worked' --> html form --> c# controller --> html (view?)
here's what I got for my 'view' (Search.cshtml)
<form action="Home/Search" method="get">
<input type="text" name="q" />
<input type="submit" value="Search" />
ok, so far so good, if I input 'worked' nothing is going to happen unless I add more code, here's c# (HomeController.cs):
public ActionResult Search(string q)
{
return this.View(q?); // so what exactly is View(q)? what is view returning? }
okay so this is where I am confused, does my string go through and become stored in 'q'? and if so, how do I get this thing to use HTML5 to output something like
<p> q </p> <!-- q = 'worked' -->
In your controller, you are calling the View(...) method incorrectly. The View(...) method expects the string parameter you're passing to be the path to the razor view you're trying to render.
A quick and simple way to pass the q variable from your controller to a view to be rendered is using ViewBag.
If you have a razor view named /Views/Search.cshtml you would do:
public class MyController : Controller
{
public ActionResult Search(string q)
{
ViewBag.Query = q;
return View("~/Views/Search.cshtml");
}
}
Then in /Views/Search.cshtml use it like this:
<p>#ViewBag.Query</p>
If you are using asp.net mvc, then please follow mvc pattern like this ..
View
#using (#Html.BeginForm("Search","Home",FormMethod.Post))
{
<b>Name : </b>
#Html.TextBox("searchTerm", null, new { #id = "txtSearch" })
<input type="submit" value="Search" />
}
Controller
[HttpPost]
public ActionResult Search(string searchTerm)
{
return View(searchTerm);
}
}
Search.cshtml
<form action="/Home/Search" method="get">
<input type="text" name="q" />
<input type="submit" value="Search" />
</form>
<p class='current-query'>#Model</p>
HomeController.cs
public ActionResult Search(string q)
{
return View((object)q); // return the model to the view (a string)
}

Passing data to a Controller method via POST

I have a 'Survey' page which is declared as follows:
#using (Html.BeginForm("Survey", "Home", new { questionList = Model.Questions }, FormMethod.Post))
{
<div class="survey">
<ol class="questions">
#foreach (Question q in Model.Questions)
{
<li class="question" id="#q.QuestionName">
#q.QuestionText<br />
#foreach (Answer a in q.Answers)
{
<input class="answer" id="#a.DisplayName" type="checkbox" /><label for="#a.DisplayName">#a.AnswerText</label>
if (a.Expandable)
{
<input type="text" id="#a.DisplayNameFreeEntry" maxlength="250" /> <span>(250 characters max)</span>
}
<br />
}
</li>
}
</ol>
</div>
<div class="buttons">
<input type="submit" value="Finish" />
</div>
}
When I'm stepping through my code, it hits the method I've set up to process their survey:
[HttpPost]
public ActionResult Survey( List<Question> questionList, FormCollection postData)
{
//Process Survey
}
However, when I step through I am finding that the variable questionList is null and the variable postData does not contain any data from the Form. Trying to access checkboxes via Request[a.Displayname also does not work.
Everything I've read indicates that this is the correct way to persist values from the Model to the submission method, and that I should be able to access the FormCollection this way.
What am I doing wrong?
You have to save questionList as a hidden field on the page. Non-primitive types do not get persisted simply by passing them in.
One way you can do that is
#Html.HiddenFor(m => m.Foo)
Or you could do it directly in HTML like this
<input type="hidden" name="Var" value="foo">
where m is your model.
The fact that the postData is empty is weird, since every input element with id inside a form tag should be passed with the POST request.
But the questionList won't be received that way, since its a list of complex class (not just a string or int), and the default ModelBinder (the thing that turns the HTTP Request Variables into parameters passed to the action method) don't support lists of complex classes.
If you want to be able to receive List you will have to implement your own binding mechanism with CustomModelBinder.
This article can help you implement it.
One problem is your checkbox and your textbox are not properly bound to your model.
You should be using #Html.CheckBoxFor and #Html.TextBoxFor

How to Pass Model from view to Controller

I'm having following view page,
#using (Html.BeginForm())
{
<fieldset class="fs">
#foreach (var item in Model.lstTravelReadyEntities)
{
<label class="Detail1"><b>Associate Id : </b>#item.Var_AssoId </label>
<label class="Detail1"><b>Vertical :</b>#item.Var_Vertical</label>
<label class="Detail1"><b>Visa ValidFrom :</b>#item.Dt_VisaValidFrom </label><br /><br />
<label class="Detail2"><b>Associate Name :</b>#item.Var_AssociateName</label>
<label class="Detail2"><b>Account Name :</b>#item.Var_AccountName</label>
<label class="Detail2"><b>Visa ValidDate :</b>#item.Dt_VisaValidTill</label><br /><br />
<label class="Detail3"><b>Grade HR :</b>#item.Var_Grade</label>
<label class="Detail3"><b>Project Name :</b>#item.Var_Project_Desc</label><br />
}
<h2> Response Details</h2><br />
Supervisor Response :<input type="radio" class="radi"
name="radio" value="yes" onclick="javascript:Getfunc(this.value);">Yes
<input type="radio"
name="radio" value="no"
onclick="javascript:Getfunc(this.value)">No
<div id="es"></div>
<input type="submit" id="insert" value="Submit"
name="Submit" onclick="javascript:InsertDetails(item);"/>
</fieldset>
}
I want pass all the values of this view page to the controller as parameters for inserting these values into the new table.How can i Achieve this?
Use #Html helpers for your controls.
Have a look at this blog entry from Scott Gu. It's about MVC2 but still applies to MVC4.
For a more concrete example, have a look at this question regarding #Html.RadioButtonFor().
Also, I would recommend hooking your events using jquery instead of inline onclick= html attributes.
<script type="text/javascript">
$("form radio").click(function(){ // or whatever selector you need
Getfunc($(this)[0].value);
});
</script>
Finaly, you will need to make sure your #Html.BeginForm posts to an [HttpPost]-decorated action on your controller that takes your Model as parameter.
What is the Problem in Existing code ?
There is no Input Type Text Control in the form and that's the reason information is not being sent to server. TextBox like controls forwards the data for sending the information to Controller Action Method.
Corrective Action
Let's say TextBox is not Required in you case. Then, you can place Hidden Fields for those View Model Properties which are required to be sent to Controller Post Action method.
Example
#using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post))
{
<fieldset class="fs">
#foreach (var item in Model.lstTravelReadyEntities)
{
<label class="Detail1">
<b>Associate Id : </b>#item.Var_AssoId
</label>
#Html.HiddenFor(i=> item.Var_AssoId) //Added Hidden Field to send this to server
<label class="Detail1">
<b>Vertical :</b>#item.Var_Vertical</label>
#Html.HiddenFor(i => item.Var_Vertical) //When post this Hidden Field will send
<label class="Detail1">
<b>Visa ValidFrom :</b>#item.Dt_VisaValidFrom
</label>
#Html.HiddenFor(i => item.Dt_VisaValidFrom)
<br />
}
<h2>
Response Details</h2>
<br />
</fieldset>
}
For explaining point of view, I excluded some of the controls. Now, You can add Hidden Fields for those Properties which are required to be sent to Action Method.
Also you should use View Models instead of Passing Individual parameter to Action Method.
Hope this will help you.
Hi try like this,
View
#using (Html.BeginForm("SaveAudit", "Controller", FormMethod.Post)
{
}
Controller
[HttpPost]
public ActionResult SaveAudit(AuditModel model, FormCollection collection)
{
}

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.

Categories

Resources