Getting data from view to create controller in asp.net MVC - asp.net-mvc-2

Getting data from view to create controller in asp.net MVC
I know this is very simple but I am just learning ASP.net MVC.
I have a Create controller and a create view (used the generator)
I can hard code data into the controller and that does get saved but I want to know how to get the data the user put on the form back into the controller.
My controller is like this.
public ActionResult Create(Seller newSeller)
{
if (ModelState.IsValid)
{
try
{
newSeller.SellerID = 34324442;
newSeller.State = "NA";
newSeller.UserType = "Seller";
newSeller.FirstName = "sdfasd";
newSeller.LastName = "dasdfadsf";
newSeller.Phone = "33333";
newSeller.Email = "dfasdfasdf";
// write to database
listingsDB.Sellers.AddObject(newSeller);
listingsDB.SaveChanges();
return RedirectToAction("Details", newSeller.SellerID);
}
catch(Exception ex)
{
}
}
return View(newSeller);
}
My view looks like this
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.SellerID) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.SellerID) %>
<%: Html.ValidationMessageFor(model => model.SellerID) %>
</div>
... Lots of propterties and then
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
I am using ASP.net MVC 2 if it matters.

You usually have two actions on the controller: one for rendering the form and one for processing the posted form values. Typically it looks like this:
public class SellerController: Controller
{
// used to render the form allowing to create a new seller
public ActionResult Create()
{
var seller = new Seller();
return View(seller);
}
// used to handle the submission of the form
// the seller object passed as argument will be
// automatically populated by the default model binder
// from the POSTed form request parameters
[HttpPost]
public ActionResult Create(Seller seller)
{
if (ModelState.IsValid)
{
listingsDB.Sellers.AddObject(seller);
listingsDB.SaveChanges();
return RedirectToAction("Details", new { id = seller.SellerID });
}
return View(seller);
}
}
then your view looks as you have shown, it contains a form and input fields allowing the user to fill each property of the model. When it submits the form, the second action will be invoked and the default model binder will automatically fill the action parameter with the values entered by the user in the form.

Related

ASP MVC 3 RAZOR dynamic form generation post

I'm trying to create asp mvc 3 page with a form with text fields that are dynamically generated based on the number of object in a list that is in the model I passed into page controller. The problem I'm running into is that whenever I post to the controller the list maintains the values but not the names of the objects in the list. Here is an example:
The Model:
public class SomeModel
{
List<Field> fieldList;
public SomeeModel()
{
fieldList = new List<Field>();
}
public string Name { get; set; }
public List<Field> FieldList
{
get
{
return fieldList;
}
}
}
The controller:
public ActionResult Preview()
{
SomeModel model = new SomeModel();
model.FieldList.Add( new Field { name = "test 1"});
model.FieldList.Add( new Field { name = "test 2"});
model.FieldList.Add( new Field { name = "test 3"});
return View(model);
}
The View:
#using (Html.BeginForm()) {
<div>
<fieldset>
<legend>Input Field List</legend>
#for (var i = 0; i < Model.FieldList.Count(); i++)
{
<div class="editor-label">
#Html.Label(Model.FieldList[i].name)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => Model.FieldList[i].value)
</div>
}
<p>
<input type="submit" value="Generate PDF" />
</p>
</fieldset>
</div>
I saw a similar post here .NET MVC Razor Dynamic Form Generation but answer runs into the same issues as I got. Hope I'm being clear! If not I'll post more info. Thanks!
You could include those names as hidden fields. This way their values will be posted to the controller action:
#for (var i = 0; i < Model.FieldList.Count(); i++)
{
#Html.HiddenFor(model => Model.FieldList[i].name)
...
}
Also instead of writing those loops I would recommend you using editor templates:
#model SomeModel
#using (Html.BeginForm())
{
<div>
<fieldset>
<legend>Input Field List</legend>
#Html.EditorFor(x => x.FieldList)
<p>
<input type="submit" value="Generate PDF" />
</p>
</fieldset>
</div>
}
and the corresponding editor template (~/Views/Shared/EditorTemplates/Field.cshtml) which will be rendered for each element of the FieldList collection:
#model Field
#Html.HiddenFor(model => model.name)
<div class="editor-label">
#Html.LabelFor(model => model.value, Model.name)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.value)
</div>
Another possibility instead of using hidden fields would be to externalize those names into some data store and then have a repository which would return them. So in your two actions you would simply query this repository for the names. Because they cannot be changed it is not necessary to include them in the HTML.

asp.net MVC the microsoft edit template not including displaying object data

I used the edit template view for visual studio and it creates a nice form for me. The problem is that none of the objects data is included in the form. for example see this code this section:
<div class="editor-label">
<%: Html.LabelFor(model => model.VideoDesc) %>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.VideoDesc) %>
<%: Html.ValidationMessageFor(model => model.VideoDesc) %>
</div>
On the server side I have the following:
public ActionResult editvid(int id)
{
using (VideoDBEntities ent = new VideoDBEntities())
{
var vids = from myRow in ent.Videos
where (myRow.VideoId == id)
select myRow;
ViewData["model"] = vids.ToList()[0];
}
return View();
}
I am new to MVC and LINQ and trying to find my feet
thanks
Andy
If you are using a strongly typed view you can pass your video object as model.
It is done by sending it as a parameter in View() method.
View can be overloaded with model object, if you have no model you can leave it empty.
in this case you can simply define video variable and pass it to the View.
using (VideoDBEntities ent = new VideoDBEntities())
{
var video = ent.Videos.SingleOrDefault(x=> x.VideoId ==id);
return View(video );
}

ASP.NET MVC2 InputHelper and List.Insert() strange behavior

I cannot make sense of this...
The simplified code below OUGHT to insert a new form field of the current time's second value.
Instead, even though the list manipulation happens correctly (as verifiable within the controller and in the debug output), the View does render an additional element, but seems to be just a copy of the final field's value (prior to submit). This can be verified by changing a field prior to submit - the values stick and the new element is a duplicate of the submitted final value.
The part that really cooks my noodle is that if I trivially change the operation from an Insert() to an Add(), the Add() works as expected!!
Using this example Model:
public class MyViewData
{
List<string> stringData = new List<string>();
public List<string> StringData { get { return stringData; } }
}
And this Controller:
public class TestController : Controller
{
public ActionResult Index()
{
return View(new MyViewData());
}
[HttpPost]
public ActionResult Index(MyViewData data)
{
data.StringData.Insert(0, DateTime.Now.Second.ToString());
return View(data);
}
}
And this View:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Forms.Controllers.MyViewData>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Test
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<%
System.Diagnostics.Debug.WriteLine("---");
for (var i = 0; i < Model.StringData.Count; i++)
System.Diagnostics.Debug.WriteLine("{0}", Model.StringData[i]);
%>
<% using (Html.BeginForm()) { %>
<% for (var i = 0; i < Model.StringData.Count; i++) { %>
<%: Html.TextBoxFor(model => model.StringData[i])%></br>
<% } %>
<div><input type="submit" value="Do it" /></div>
<% } %>
</asp:Content>
This is the normal behavior of standard HTML helpers and is by design. When rendering the input field they will first look at the request POSTed values and only after in the ViewData and view model. This basically means that you cannot change POSted values in your controller action.
So if you have a form with an input field:
<%= Html.TextBoxFox(x => x.Id) %>
which is posted to the following action
[HttpPost]
public ActionResult Index(MyModel model)
{
model.Id = "some new value";
return View(model);
}
when rendering the view back the html helper will use the posted value. You could either write a custom html helper that does the job for you or handle it manually (absolutely not recommended but for the record):
<input type="text" name="StringData[<%= i %>]" value="<%= Model.StringData[i] %>" />

Passing Parameters from textboxes in a view to a controller in ASP.Net MVC2

I am trying out ASP.Net MVC2 by building a small sample website which, amongst other features provides the user with a 'Contact Us' page. The idea is to allow a user to enter their name, email address, message subject and message. To send the message the user clicks on an ActionLink. This is the view:
<% Html.BeginForm(); %>
<div>
<%: Html.Label("Name")%>
<br />
<%: Html.TextBox("txtName", "",new { style = "width:100%" })%>
<br />
<%: Html.Label("Email address")%>
<br />
<%: Html.TextBox("txtEmail", "", new { style = "width:100%" })%>
<br />
<%: Html.Label("Subject")%>
<br />
<%: Html.TextBox("txtSubject", "", new { style = "width:100%" })%>
<br />
<%: Html.Label("Message")%>
<br />
<%: Html.TextBox("txtMessage", "", new { style = "width:100%" })%>
</div>
<div style='text-align: right;'>
<%:
Html.ActionLink("Send", "SentEmail", new { name = Html.g, sender = "txtEmail", subject = "txtSubject", message="txtMessage" })
%>
</div>
<% Html.EndForm(); %>
The idea is once the ActionLink has been clicked a method in the controller is called into which the username, email address, subject and message will be passed. This is the method in the controller:
public ActionResult SentEmail(string name, string sender, string subject, string message)
{
//Send email here and then display message contents to user.
ViewData["Name"] = name;
ViewData["Message"] = message;
ViewData["ThankyouMessage"] = "Thank you for contacting us. We will be in touch as soon as possible.";
return View();
}
However... when I click the link the values which are passed into the method are null. I have tried creating a route to do this but it doesn't work either. Should I be using another method?
Thank you,
Morris
Actually to achieve what you want to is easier than in your sample. Never heard about Model classes, Model Binder and strong typed views? Here thery are
Model class
public class ContactUsModel
{
public string Name { get; set; }
public string Email { get; set; }
public string Subject { get; set; }
public string Message { get; set; }
}
Then in your controller you should have two action: the first that show the form with default values and the second that receive the form with the data placed by the user. These two actions maps exactly to the HttpGet and HttPost verbs.
[HttpGet]
public virtual ActionResult ContactUs() {
ContactUsModel model = new ContactUsModel();
return View(model);
}
[HttpPost]
public virtual ActionResult ContactUs( ContactUsModel model ) {
//e.g. Save the contact request to database
}
To use this your view shal be strong typed to the ContactUsModel class
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ContactUsModel>" %>
<% using (Html.BeginForm()) { %>
<div>
<%: Html.LabelFor(model => model.Name) %><br />
<%: Html.TextBoxFor(model => model.Name, new { style = "width:100%" })%>
</div>
<div>
<%: Html.LabelFor(model => model.Email) %><br />
<%: Html.TextBoxFor(model => model.EMail, new { style = "width:100%" })%>
</div>
<div>
<%: Html.LabelFor(model => model.Subject) %><br />
<%: Html.TextBoxFor(model => model.Subject, new { style = "width:100%" })%>
</div>
<div>
<%: Html.LabelFor(model => model.Message) %><br />
<%: Html.TextAreaFor(model => model.Message, new { style = "width:100%" })%>
</div>
<div>
<input type="submit" value="Save" />
</div>
<% } %>
the magic of everything this is called ModelBinder. Please read more and more about MVC here.
The action link isn't going to trigger a http post nor will it pass in the values of your form fields, just a http get and not passing through any form data - ideally you'd use an input submit button to post the data. What is certain is that it is good practise that any request that causes creating/updating of data should be done via a http post.
Submit button would just be like.
<input type="submit" value="Send" />
You then have several ways of accessing the form data firstly you could use a FormCollection to access the data
[HttpPost]
public ActionResult SendEmail(FormCollection collection)
{
string email = collection["txtEmail"];
...
}
Secondly you could use the method parameters and rely on model binding, but you must make sure field names match the parameter name so
<%: Html.TextBox("txtEmail", "", new { style = "width:100%" })%>
...would require...
[HttpPost]
public ActionResult SendEmail(string txtEmail)
{
...
}
If this form isn't being posted to the same action thats return the view then you'd also need to change your begin form tag, ideal you should use 'using' with it as well. So you'd get:
<% using (Html.BeginForm("SendEmail", "<controller-name>"))
{ %>
.... form fields in here ...
<input type="submit" value="Send" />
<% } %>
If the button isn't suitable for your design you could use something like:
<input type="image" src="<%: Url.Content("~/Content/images/myimage.gif") %>" value="Send" />
This would have the same effect. To trigger a post from an a tag though you'd need to look at using javascript, I can't remember the exact syntax but off hand I think if you used jquery you'd be looking at something like: (form a single form page only)
Send
But then you create a dependency on javascript where as really you should try have your site degrade gracefully so it can be used by visitors with javascript disabled. There are perhaps more advanced way of achieving this whilst meeting design requirements but that can get heavily into client side code which is probably outside of what you want for your sample.

Having difficulty with ModelBinding and Dictionary, ASP.NET MVC 2.0

Using the following model, I expect that when the Submit button is hit, the Edit Method to Fire, and the model parameter to have the adjusted values. But it keeps returning an instance of the class with all null values. It is as if no model binding ever happens.
class Trait
{
string Name { get; set; }
// other properties
}
class DesignViewModel
{
Dictionary<Trait, int> Allocation { get; set; }
}
Controller
public ActionResult Create()
{
var model = new DesignViewModel();
// retrieve traits from database
foreach(var trait in Repository.Traits)
model.Allocation.Add(trait, 0);
return View(model);
}
[HttpPost]
public ActionResult Edit(DesignViewModel model)
{
// nothing works yet, so I don't have a lot of code here...
}
HTML
Top Level Page
<%# Page Title="" Language="C#" MasterPageFile="~/Areas/Setup/Views/Shared/Setup.master"
Inherits="System.Web.Mvc.ViewPage<OtherModel>" %>
<% Html.RenderAction("Design", "Test"); %>
Partial View
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DesignViewModel>" %>
<% using (Html.BeginForm("Edit", "Test", FormMethod.Post ) ) {%>
<div id="eq">
<% foreach (var trait in Model.Allocations) { %>
<div style="margin: 15px;">
<%: trait.Key.Name %>
<br />
<span class="slider"></span>
<%: Html.TextBox(trait.Key.Name, trait.Value, new { #class = "spent" , #readonly = "readonly" })%>
</div>
<% } %>
</div>
<p>
<input type="submit" value="Submit" />
</p>
<% } %>
You need to add [HttpPost] to your Edit method for it to be fired during POST requests.