ASP.NET MVC Form Post - c#

<form action="/Villa/Add" method="post">
<table>
<tr>
<td>
Name:
</td>
<td>
<%= Html.TextBox("name") %>
<%= Html.ValidationMessage("Name") %>
</td>
</tr>
<tr>
<td>
</td>
<td>
<input type="submit" value="Add" />
</td>
</tr>
</table>
</form>
My form is above, how do I retrieve the values in my controller?
Thanks a lot in advance! Hard to find the right material because of different Previews of MVC being released and being different.

This works for ASP.Net MVC Beta.
public ActionResult Add( string name ) {
....
}
or
public ActionResult Add( FormCollection form ) {
string name = form["Name"];
}
or
public ActionResult Add( [Bind(Prefix="")]Villa villa ) {
villa.Name ...
}

Have you tried something like this? Pseudocode...
public class VillaController : Controller
{
public ActionResult Add(string name)
{
// Code...
}
}

It belongs to your url routes, you defined.
In your case the form ist looking for an controller named "Villa" and the action inside of it named "Add".
Maybe you should read ScottGu's blog post: http://weblogs.asp.net/scottgu/archive/2008/09/02/asp-net-mvc-preview-5-and-form-posting-scenarios.aspx

Related

How to post values using DisplayFor [duplicate]

This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Closed 4 years ago.
I can't get the values in controller from the post method used on the view and I don't know why. I saw a lot of forums and I thought that I was doing the right thing, but it doesn't seem to be the correct way to do because I can't get the values.
First I was using just the DisplayFor but that just shows and not pass the values then I join the HiddenFor to use that like an input like I saw in other forums. But the model always returns zero values.
AtribuiĆ§Ć£oController:
public IActionResult Create(List<Main> main)
{
return RedirectToAction(nameof(Index));
}
Index.cshtml:
#model ModelsLibrary.Main
<form asp-action="Create">
<table class="table">
<thead>
<tr>
<th>
<label>Disciplina</label>
</th>
<th>
<label>Turno</label>
</th>
<th>
<label>Tipologia</label>
</th>
<th>
<label>Docente</label>
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Turno)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.MetaDisciplina.Nome)
#Html.HiddenFor(modelItem => item.MetaDisciplina.Nome)
</td>
<td>
#Html.DisplayFor(modelItem => item.LetraTurno)
#Html.HiddenFor(modelItem => item.LetraTurno)
</td>
<td>
#Html.DisplayFor(modelItem => item.Tipologia.Tipo)
#Html.HiddenFor(modelItem => item.Tipologia.Tipo)
</td>
<td>
<select asp-for="Docente" asp-items="ViewBag.Docente"></select>
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
Index Method
[HttpGet]
public IActionResult Index()
{
var Turno = new List<Turno>();
Main main = new Main();
main.Turno = Turno;
ViewData["Ano"] = new SelectList(_context.AnoLetivo, "Ano", "Ano");
return View(main);
}
Hi have a problem binding the values to the controller. The method create should get values in the attributes but i don't know why and heaven don't know why the values not pass... I not pass a list to the view but i want one list in the create method.... If someone can help.
Your problem is in your Controller. Your create method do redirect to your Index method but you don't pass your List main
I think your code should be like this:
[HttpGet]
public ActionResult Index()
{
List<Main> main = (List<Main>)TempData["yourData"];
if (main == null)
{
main = new List<Main>();
}
return View("Index", main);
}
public IActionResult Create(List<Main> main)
{
TempData["yourData"] = main;
return RedirectToAction(nameof(Index));
}
The way your want to redirect your data is called the POST-REDIRECT-GET pattern. If your want more information about it, visit this website : https://andrewlock.net/post-redirect-get-using-tempdata-in-asp-net-core/
--------------------EDIT--------------------
You have a binding problem while passing data from View to Controller. You can use an TempData in your View to pass your complete Model to your controller:
#model List<WebApplication1.Models.TestObject>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#foreach (var item in Model)
{
#Html.DisplayFor(m => item.ToDisplay)
}
<form action="/Home/Create" method="post">
<button type="submit">Submit</button>
</form>
<script>
$('form').submit(function() {
#{ TempData["FullModel"] = Model; }
});
</script>
In this exemple, i use a jquery script to create a TempData and send it to the controller
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
List<TestObject> main = (List<TestObject>)TempData["yourData"];
if (main == null)
{
main = new List<TestObject>();
main.Add(new TestObject("1"));
main.Add(new TestObject("2"));
main.Add(new TestObject("3"));
main.Add(new TestObject("4"));
main.Add(new TestObject("5"));
}
return View("Index", main);
}
[HttpPost]
public ActionResult Create()
{
List<TestObject> main = (List<TestObject>)TempData["FullModel"];
TempData["yourData"] = main;
return RedirectToAction(nameof(Index));
}
}
Hope it was helpfull

Whats the Appropriate Method to pass 2 different Models to the Controller from a View in MVC4

I am using MVC4 with SimpleMembership. MVC has setup my UserProfile table and I've modified the Registration View to accomodate my layout. Everything worked great until I determined that I wanted to include some additional information from my user that best fit within the context of another already existing Model.
Typically my approach to passing more than one Model from my View to the Controller has been to employ Tuples. Historically this has worked out great for me and I've never had any real issues until now.
My Registration Form resembles this:
#model Tuple<MyNamespace.Models.RegisterModel,MyNamespace.Models.MembershipDetail>
#using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
#Html.AntiForgeryToken()
<table style="border-collapse: collapse; border-spacing:0px; border-width:0px; margin: 0px; width:100px; padding: 0 0 0 0px; background-color:#2e2e2e;">
<tr>
<td>
Profile Name
</td>
<td>
#Html.TextBoxFor(m => m.Item2.ProfileName)
</td>
</tr>
<tr>
<td>
#Html.LabelFor(m => m.Item1.UserName)
</td>
<td>
#Html.TextBoxFor(m => m.Item1.UserName)
</td>
</tr>
<tr>
<td>
#Html.LabelFor(m => m.Item1.Password)
</td>
<td>
#Html.PasswordFor(m => m.Item1.Password)
</td>
</tr>
<tr>
<td>
#Html.LabelFor(m => m.Item1.ConfirmPassword)
</td>
<td>
#Html.PasswordFor(m => m.Item1.ConfirmPassword)
</td>
</tr>
<tr>
<td>
<button type="submit" id="btnSubmitForm" value="Register">Register</button>
</td>
</tr>
</table>
#Html.Partial("_ValidationSummary",ViewData.ModelState)
}
The Register Method of my Controller is similar to this:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model, MembershipDetail member)
{
if (ModelState.IsValid)
{
try
{
// Do something with the data
}
catch(MembershipCreateUserException e)
{
ModelState.AddModelError("",ErrorCodeToString(e.StatusCode));
}
}
return View(model);
}
Whenever I debug this code after the click of the Submit button, I note that both Models returned to the controller are empty. The contained fields are either null, 0 or Empty Strings and I cannot figure out why.
To add to this mystery, if I remove the tuple from the top of the view and re-assign it as a single Model as such:
#model MyNamespace.Models.RegisterModel
And replace the tuple references from the code (e.g. m.Item1.Property, m.Item2.Property) with the 1 Model inferred reference (m.Property and etc); then the data passed in from the TextBox helpers is appropriately assigned to the model and the model is populated when I debug the code.
Now, I know I could simply add a few other fields to the UserProfile table and use them in my Model to alleviate the Tuple altogether but then I am duplicating data in my schema which is not an ideal solution. And keeping in mind that though my sample code provided here only contains 1 element of the 2nd Model, it will actually be more than 1.
So why don't the Models get populated when using the Tuple and is there a more appropriate way to go about solving this problem? Or can I not mix Model data on a single form submission???
First of all , it is not a good practice to use Tuple as model, because it is hard to read the code. You should write page's own viewmodels for that.
For this example like :
public class SomeViewModel{
public RegisterModel RegisterModel { get; set;}
public MembershipDetail MembershipDetail {get; set;}
}
it is easy to implement and will work as you want.
However if you want to use Tuples on the view as model.
You should get Your post action like
public ActionResult Register(Tuple<RegisterModel,MembershipDetail> model)
{
.... // do something..
}
Because the form html will be created like :
<input name="Item1.ProfileName" />
You can see , it will try to send Item1.Profile name which is not supported by default model binder to convert it to your own classes.. it will expect a Tuple or a class like :.
public class TheClass {
public RegisterModel Item1 {get; set;}
public MemberhipDetail Item2 {get; set;}
}
which basically just like the viewmodel

Razor MVC doubts in a small sample program

I just started studying MVC few days back. As far as I know, I did a small sample program. But some doubts I been facing. I am posting my doubts and code below. Please help me to understand it clearly.
Here I created four views and controller and a student class.
StudentClass
public class Student
{
public string Name { get; set; }
public string Age { get; set; }
public string Place { get; set; }
}
ViewOne
#model MyTestMVCApp.Models.Student
#{
ViewBag.Title = "ViewOne";
}
#using (Html.BeginForm())
{
<table style="border-color:Black;">
<tr>
<td>Name</td><td>Age</td><td>Place</td>
</tr>
<tr>
<td>--</td><td>--</td><td>--</td>
</tr>
</table>
<label>Enter Name : </label>
#Html.TextBoxFor(model => model.Name, new { name = "name"});
<input name="submit" type="submit" id="btnStart" class="button" value="Start Filling Details" />
ViewTwo.cshtml
#model MyTestMVCApp.Models.Student
#{
ViewBag.Title = "ViewTwo";
}
#using (Html.BeginForm())
{
<table style="border-color:Black;">
<tr>
<td>Name</td><td>Age</td><td>Place</td></tr>
<tr>
<td>#Model.Name</td><td>#Model.Age</td><td>#Model.Place</td>
</tr>
</table>
<label>Enter Age : </label>
#Html.TextBoxFor(model => model.Age, new { name = "age" });
<input name="submit" type="submit" id="btnNext" class="button" value="Next" />
}
ViewThree.cshtml
#model MyTestMVCApp.Models.Student
#{
ViewBag.Title = "ViewThree";
}
#using (Html.BeginForm())
{
<table style="border-color:Black;">
<tr><td>Name</td><td>Age</td><td>Place</td></tr>
<tr><td>#Model.Name</td><td>#Model.Age</td><td>#Model.Place</td></tr>
</table>
<label>Enter Age : </label>
#Html.TextBoxFor(model => model.Place, new { name = "place" });
<input name="submit" type="submit" id="btnNext" class="button" value="Next" />
}
ViewFour.cshtml
#model MyTestMVCApp.Models.Student
#{
ViewBag.Title = "ViewFour";
}
#{
<table style="border-color:Black;">
<tr><td>Name</td><td>Age</td><td>Place</td></tr>
<tr><td>#Model.Name</td><td>#Model.Age</td><td>#Model.Place</td></tr>
</table>
}
MyViewController.cs
public class MyViewController : Controller
{
public ActionResult ViewOne()
{
Student student = new Student();
return View(student);
}
[HttpPost]
public ActionResult ViewOne(Student student)
{
return View("ViewTwo", student);
//return RedirectToAction("ViewTwo",student);
}
[HttpPost]
public ActionResult ViewTwo(Student student)
{
return View("ViewThree", student);
//return RedirectToAction("ViewThree", student);
}
[HttpPost]
public ActionResult ViewThree(Student student)
{
return View("ViewFour", student);
}
}
My doubts
doubt 1. On the button click in ViewTwo,
[HttpPost]
public ActionResult ViewOne(Student student)
{
}
is debugging instead of ViewTwo's [HttpPost] actionresult.. Why ?
doubt 2. How can I pass the same instance of the student object I created in the ViewOne to all other Views , because my need is
On ViewOne, I get 'name' property of the student, then I pass the same object to ViewTwo.
On ViewTwo, I get 'age' property of the student, then I pass the same object to ViewThree.
On ViewThree, I get 'place' property of the student, then I pass the same object to ViewFour.
On ViewFour I display all the values of the student that I get through the above views.
It looks like you are returning ViewTwo from ViewOne's post action. When you do that you're still routing to the ViewOne action. The code below will show in your address bar as ViewOne, even though you're returning ViewTwo. Looks like you had the right idea at some point where you had a RedirectToAction call but you don't have an HttpGet for the ViewTwo action.
[HttpPost]
public ActionResult ViewOne(Student student)
{
return View("ViewTwo", student);
//return RedirectToAction("ViewTwo",student);
}
Another option, and this would probably be useful for you since you're trying to pass your Student object, would be to use RedirectToRoute where you pass the Student name, id or some other identifying item, as a parameter in the route. So the uri would end up looking something like this: ../MyView/ViewTwo/Joe
Because you are calling from ViewOne. if you want execute ViewTwo Action then use as below
#using (Html.BeginForm("ViewTwo", "MyView", FormMethod.Post))
It looks like it is the view definition that you have missed a small bit of logic.
the reason why you are hitting ViewOne on postback is because you are not setting the values the form it posting back to.
so in your ViewOne.cshtml and subsequent views you would need
#Html.BeginForm("ViewTwo","MyViewController")
{
//View code
}
The HTML.BeginForm will render with the RouteData if you do not provide it in the call for begin form.

Simple MVC error flow

I am using ASP MVC 4.0 and would like to understand the basics of custom validation. In this particular case, the model is not at all strongly typed with the controller or view so I need something different.
What I'd like to do is accept a new username on signup to my service, look in the database, and re-present the original form with a message if that username is taken.
This is my input form:
#{
ViewBag.Title = "Index";
}
<h2>New account</h2>
<form action= "#Url.Action("submitNew", "AccountNew")" method="post">
<table style="width: 100%;">
<tr>
<td>Email:</td>
<td> </td>
<td><input id="email" name="email" type="text" /></td>
</tr>
<tr>
<td>Password:</td>
<td> </td>
<td><input id="password" name="password" type="password" /></td>
</tr>
<tr>
<td>Confirm Password:</td>
<td> </td>
<td><input id="passwordConfirm" name="passwordConfirm" type="password" /></td>
</tr>
<tr>
<td></td>
<td> </td>
<td><input id="Submit1" type="submit" value="submit" /></td>
</tr>
</table>
</form>
and here is my controller method upon submit:
public ActionResult submitNew()
{
SomeService service = (SomeService)Session["SomeService"];
string username = Request["email"];
string password = Request["password"];
bool success = service.guestRegistration(username, password);
return View();
}
If success is false, I'd just like to re-present the form with a message indicating so. I'm missing the basics of this error flow. Would you please help? thanks in advance.
You could add a ViewBag item
bool success = service.guestRegistration(username, password);
if (!success)
{
ViewBag.Error = "Name taken..."
}
return View();
But you should create a view model...
public class ViewModel
{
public string UserName {get; set;}
//...other properties
}
...strongly type your view and use the built in html helpers...
#model ViewModel
//...
#using BeginForm("SubmitNew", "AccountNew", FormMethod.Post)()
{
//...
<div>#Html.LabelFor(m => m.Username)</div>
<div>#Html.TextBoxFor(m => m.Username)</div>
<div>#Html.ValidationMessageFor(m => m.Username)</div>
}
...and leverage ModelState in the controller
[HttpPost]
public ActionResult SubmitNew(ViewModel viewModel)
{
if(ModelState.IsValid)
{
SomeService service = (SomeService)Session["SomeService"];
bool success = service.guestRegistration(viewModel.username, viewModel.password);
if (success)
{
return RedirectToAction("Index");
}
ModelState.AddModelError("", "Name taken...")"
return View(viewModel);
}
}
...or even write your own validator and just decorate your model property, eliminating the need to check success in the controller.

MVC2 scaffolding - can't see any data

I'm having a problem seeing any data in my MVC2 application.
I'm using your typical scaffolding setup, but when I view the index or details page I see no data at all.
I'm sure I'm missing something simple here as I get no errors when compiling or running.
Here is my model(Users.cs):
public class Users
{
public string UserName { get; set; }
[Required(ErrorMessage = "The Customer ID is required.")]
public string CustomerID { get; set; }
}
Here are the 2 controller(UsersController.cs) actions that matter:
public class UsersController : Controller
{
static List<Users> users = new List<Users>();
//
// GET: /Users/
public ActionResult Index()
{
return View(users);
}
//
// GET: /Users/Details/5
public ActionResult Details(Users u)
{
return View(u);
}
}
And here are my views.
Users/Index.aspx
<table>
<% foreach (var item in Model) { %>
<tr>
<td>
<%= Html.ActionLink("Edit", "Edit", new { id=item.UserName }) %> |
<%= Html.ActionLink("Details", "Details", item )%> |
<%= Html.ActionLink("Delete", "Delete", new { id = item.UserName })%>
</td>
<td>
<%= Html.Encode(item.UserName) %>
</td>
<td>
<%= Html.Encode(item.CustomerID) %>
</td>
</tr>
<% } %>
</table>
<p>
<%= Html.ActionLink("Create New", "Create") %>
</p>
Users/Details.aspx
<fieldset>
<legend>Fields</legend>
<div class="display-label">UserName</div>
<div class="display-field"><%= Html.Encode(Model.UserName) %></div>
<div class="display-label">CustomerID</div>
<div class="display-field"><%= Html.Encode(Model.CustomerID) %></div>
</fieldset>
<p>
<%= Html.ActionLink("Edit", "Edit", new { id=Model.UserName }) %> |
<%= Html.ActionLink("Back to List", "Index") %>
</p>
All the pages load just fine with no errors, but no data is shown. If I run the debugger the users list has 0 entries.
I am using SQL Server. My connection string is in my web.config in the typical fashion:
My database has user data in it already. It was generated with the default asp.net Web Site Administration Tool, which I am using for authentication. This works perfectly.
So what am I doing wrong? Any help is appreciated and if I need to give more info please let me know.
Your UserController (as explained in comment on OP) instantiates your list of users with no data.
If you want to seed data, consider changing the declaration as follows:
public class UsersController : Controller
{
// static List<Users> users = GetSeededData(); -
// don't store a list locally, it isn't necessary if you have a database
// consider holding the context instead perhaps?
protected MyContext context = new MyContext();
//
// GET: /Users/
public ActionResult Index()
{
return View(context.users.ToList());
}
//
// GET: /Users/Details/5
public ActionResult Details(int userId)
{
return View(context.Users.SingleOrDefault(x => x.UserId.Equals(userId));
}
}
A quick suggestion regarding your "persistance" (ignore this if you like, just a friendly tip)...
Consider introducting a persistance layer. That is, if you want to persist data, consider storing it in a database, xml file, etc. Take a look here. It's a great resource on MVC with lots of samples and tutorials, and half way down under the "Models" section it introduces you to the Entity Framework which can be used to store, retrieve, and update your data on a database quite nicely.

Categories