MVC2: How submit data from Partial view to his controller? - asp.net

I have this model:
public class Package
{
public string CustomerName { get; set; }
public List<Product> Products { get; set; }
public int Id { get; set; }
}
public class Product
{
public int Quantity { get; set; }
public string Name { get; set; }
public int Id { get; set; }
}
I have a Create's view for creating a new Package and one or many Create product's PartialView.
How I can submit the Product informations to the Product's controller without leave the View?
Here is my Product's Partialview code:
<% using (Ajax.BeginForm("Create", "Product", new AjaxOptions())) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Name) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Name) %>
<%: Html.ValidationMessageFor(model => model.Name) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Quantity) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Quantity) %>
<%: Html.ValidationMessageFor(model => model.Quantity) %>
</div>
<%-- <p>
<input type="submit" value="Create" />
</p>--%>
</fieldset>
<% } %>
Thank you

You can use AJAX to solve your problem. The code pode below post 3 values to YourController in YourAction.
jQuery('#YourButton').click(function (event) {
var jqxhr = $.post("YourController/YourAction", {
lastName: $("#tbLastName").val(),
firstName: $("#tbFirstName").val(),
id: $("#id").val()
},
function (data) {
$('#WhereResultAppear').html(data); //can be deleted
})
.success(function () {
$('#InCaseOfSuccess').html(data); //can be deleted
})
.error(function (jqXHR, status, error) {
$('#InCaseOfError').html(data); //can be deleted
})
.complete(function () {
$('#WhenActionIsComplete').html(data); //can be deleted
});
});

Give an id to your form in the partial view. and then use JQuery to send data by serializing the form.
$.post("controller/action", $("#formId").serialize(),
function(data) {
alert("Data Loaded: " + data);
});
And in the controller
Package pakage = new Package();
UpdateModel(pakage );

Although you can write code to serialize the data as the other answers mention, I would consider surrounding the fields in an
#using (Ajax.BeginForm("ActionOnController", new AjaxOptions{}))
{
}
This will do it all for you (as long as you include the necessary javascript e.g. jquery.unobtrusive-ajax.min.js)
Take a look at the AjaxOptions documentation. This allows you to (amongst other things) update another section after posting the values back. You can use this to indicate success
Martin

Related

Server Side DropDown validation firing always

My MVC 2 dropdown validation fire always even though i select a item from the list. I checked from firebug the dropdown is bind correcly with expected values.
Model:
public class Delivery
{
public int DeliveryID { get; set; }
[Required(ErrorMessage = "Please Select a Stock")]
public int? StockID { get; set; }
[Required(ErrorMessage = "Please Enter Expenses")]
public double OtherExpenses { get; set; }
public double Total { get; set; }
[Required(ErrorMessage = "Please Enter Description")]
public string Description { get; set; }
[Required(ErrorMessage = "Please Enter Arrived Date")]
public DateTime ArrivedDate { get; set; }
public string StockDescription { get; set; }
public IEnumerable<Stock> lstStock { get; set; }
}
Controller:
public ActionResult Create()
{
DeliveryRepository rep = new DeliveryRepository();
var model = new Delivery
{
lstStock = rep.GetStock()
};
return View(model);
}
//
// POST: /Delivery/Create
[HttpPost]
public ActionResult Create(FormCollection collection)
{
try
{
Delivery del = new Delivery();
DeliveryRepository rep = new DeliveryRepository();
TryUpdateModel(del);
if (ModelState.IsValid)
{// TODO: Add insert logic here
del.ArrivedDate = Convert.ToDateTime(Request.Form["ArrivedDate"]);
del.Description = Request.Form["Description"];
del.OtherExpenses = Convert.ToDouble(Request.Form["OtherExpenses"]);
del.StockID = Convert.ToInt32(Request.Form["StockID"]);
del.Total = Convert.ToDouble(Request.Form["lblTotal"]) + del.OtherExpenses;
rep.Create(del);
rep.Save();
return RedirectToAction("Index");
}
else
{
var model = new Delivery
{
lstStock = rep.GetStock()
};
return View(model);
}
}
catch
{
return View();
}
}
View:
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.Label("Select Stock") %>
</div>
<div class="editor-field">
<%: Html.DropDownListFor(x => x.lstStock, new SelectList(Model.lstStock, "StockID", "Description"), "-- Please Select a Stock --")%>
<%: Html.ValidationMessageFor(model => model.StockID)%>
</div>
<div id="clslbl">
<br />
<label id="lblTotal"></label>
</div>
<br />
<div class="editor-label">
<%: Html.LabelFor(model => model.OtherExpenses) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.OtherExpenses) %>
<%: Html.ValidationMessageFor(model => model.OtherExpenses) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Description) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Description) %>
<%: Html.ValidationMessageFor(model => model.Description) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.ArrivedDate) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.ArrivedDate) %>
<%: Html.ValidationMessageFor(model => model.ArrivedDate) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
Issue was with my view
<div class="editor-field">
<%: Html.DropDownListFor(x => x.lstStock, new SelectList(Model.lstStock, "StockID", "Description"), "-- Please Select a Stock --")%>
<%: Html.ValidationMessageFor(model => model.StockID)%>
</div>
Should be changed as
<div class="editor-field">
<%: Html.DropDownListFor(x => x.StockID, new SelectList(Model.lstStock, "StockID", "Description"), "-- Please Select a Stock --")%>
<%: Html.ValidationMessageFor(model => model.StockID)%>
</div>

MVC 2 model with IList<T> properties binding question

I'm working on an MVC 2 project and I have a model that looks like this:
public string AccountNumber { get; set; }
public IList<Equipment> ShippedEquipmentList { get; set; }
and a view that has a button for adding a new piece of equipment. Clicking the button dynamically adds new textboxes to the view for specifying another piece of equipment. The partial view it renders looks like this:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<RmaMVC.Models.Entities.Equipment>" %>
<div class="editorRow">
Item: <%: Html.TextBoxFor(x => x.ItemID); %>
Value: <% Html.TextBoxFor(x => x.Description); %>
</div>
My question is: how do I bind this data to the model? When the controller gets called the ShippedEquipmentList comes back as null.
Edit: here is what I have so far. My model looks like this:
public string AccountNumber { get; set; }
public IList<Equipment> ShippedEquipmentList { get; set; }
FormInputs()
{
ShippedEquipmentList = new List<Equipment>();
// adding a single blank piece of equipment so that the length isn't 0
Equipment blank = new Equipment();
ShippedEquipmentList.Add(blank);
}
my main view is this:
<% Html.BeginForm(); %>
<div id="items">
</div>
<%: Ajax.ActionLink("add new", "AddNewEquipment", new AjaxOptions {
UpdateTargetId = "items", InsertionMode = InsertionMode.InsertAfter }) %>
<input type="submit" value="submit" />
<% Html.EndForm(); %>
my controller:
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(FormInputs input)
{
return View(input);
}
public ActionResult AddNewEquipment()
{
return PartialView("~/Views/RMA/EditorTemplates/Equipment.ascx");
}
the partial view that generates the text boxes for the equipment:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<RmaMVC.Models.Entities.Equipment>" %>
<p>
<%: Html.TextBoxFor(x => x.ItemID) %>
<%: Html.TextBoxFor(x => x.Description) %>
<%: Html.TextBoxFor(x => x.Quantity) %>
<%: Html.TextBoxFor(x => x.SerialNumber) %>
</p>
Check this: Model Binding To A List

How do I access my post data in a asp.net mvc editor view?

I have gotten this semi autogenerated code, but I am uncertain where the Post data is saved and how I access the variables in my controller so I can validate and upload it to my database.
#model FirstWeb.Models.Picture
#{
ViewBag.Title = "Upload et billede";
}
<h2>Upload et billede</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<input type="file" name="file" id="file" />
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ConcertYear)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ConcertYear)
#Html.ValidationMessageFor(model => model.ConcertYear)
</div>
<p>
<input type="submit" value="Upload" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Tilbage til billeder", "Index")
</div>
It seems that you are trying to upload files here. Checkout the following blog post. You will need to use a multipart/form-data enctype for your form in order to be able to upload files. So the first step is to fix your form definition:
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
...
}
then update your view model so that it takes the uploaded file as property:
public class Picture
{
public HttpPostedFileBase File { get; set; }
public string Title { get; set; }
public int ConcertYear { get; set; }
... some other properties used in the view
}
and and finally have your controller POST action take this view model as parameter:
[HttpPost]
public ActionResult Foo(Picture model)
{
if (!ModelState.IsValid)
{
// there were validation errors => re-display the view
return View(model);
}
// the model is valid at this stage => check if the user uploaded a file
if (model.File != null && model.File.ContentLength > 0)
{
// the user uploaded a file => process it ...
}
...
}
The Edit action should take your model as a parameter.
Its proeprties will have the edited values.

MVC2: Is rendering List<object> possible in Create context?

I have this Model:
public class Package
{
public string CustomerName { get; set; }
public List<Product> Products { get; set; }
}
public class Product
{
public int Quantity { get; set; }
public string Name { get; set; }
}
When I add the Create's view, the code is:
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.CustomerName) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.CustomerName) %>
<%: Html.ValidationMessageFor(model => model.CustomerName) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
How manage the Products list?
Can I get a button or something to create a new product and add it to the Products list?
Thank you
for creating buttn you can also do this use HTML.ActionLink() or Ajax.ActionLink() defined as a button like:
<% Response.Write(Html.ActionLink("Add Product", "Create", new { id = tId, tNum = tNum }, new { #class = "oldVal" })); %>
it'll create a button on your page, and here you can see different attributes (so just check them out you'll find it useful) ... and from both of this which to use is more depends upon your desired action ...
and in your controller:
public ActionResult Create()
{
// do same as mentioned by [gnome][1]
}
here is the example: modal popup, declared as a partial view of page
[partial view using Ajax.ActionLink()]
using (Ajax.BeginForm("Login", "Users", null, new AjaxOptions() { UpdateTargetId = "divLoginPopupContent" }))
{
Response.Write(Html.ValidationSummary(true));
%>
<ul class="chooseQuestion">
<li>
<div class="short">
<%= Html.LabelFor(model => model.LoginEmail)%>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model.LoginEmail)%>
<%= Html.ValidationMessageFor(model => model.LoginEmail)%>
</div>
</li><li>
<div class="short">
<%= Html.LabelFor(model => model.LoginPassword)%>
</div>
<div class="editor-field">
<%= Html.PasswordFor(model => model.LoginPassword)%>
<%= Html.ValidationMessageFor(model => model.LoginPassword)%>
</div>
</li><li>
<div class="checkbox">
<%= Html.CheckBoxFor(model => model.Remember)%>
<%= Html.LabelFor(model => model.Remember)%>
</div>
</li><li>
<input type="submit" class="button" value="Login" id="btnLoginSubmit" />
<div id="divlogin_ajaxloading" style="display:none; vertical-align:top; text-align:center;"><img alt="" src="/images/ajax-loader.gif" /></div>
</li>
</ul>
}
your partial view action:
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.LoginEmail, model.LoginPassword))
{
return Redirect("/MyPage");
}
else
{
ModelState.Clear();
return PartialView("LoginPopup", new LoginModel());
}
}
}
Just typed this up, haven't tested it but the basic idea is to list your products on the customer view with a button to add a new product for a customer.
To list Products for Customer:
<table>
<% foreach(var p in Customer.Products) { %>
<tr>
<td><%: p.Quantity %></td>
<td><%: p.Name %></td>
</tr>
<% } %>
</table>
<p><%: Html.ActionLink("Add Product", "Create", new { controller = 'Products' }, new { id = 'addProduct'}) %>
<div id="dialog"></div>
To add a new Product for a customer you could use jQuery UI to show a dialog; just pass the Customer Id
// assuming you've included jquery-ui
<script type="text/javascript">
$(document).ready(function() {
$('#dialog').dialog({
autoOpen : false,
button : {
'Save' : function() {
$.ajax({
url : $('#addProduct').attr('href'),
type : 'get'
success : function() {
alert('Product added!');
}
});
},
'Cancel' : function() {
$('#dialog').dialog('close');
}
}
});
$('#addProduct').click(function() {
var customerId = $('#CustomerId').val();
$('#dialog').dialog('open');
$('#Customer_Product_Id').val(customerId); // assuming there's a hidden field on the form
});
});
</script>
In your product controller return a partial
public ActionResult Create()
{
List<Product> products = new List<Product>() {
new Product() { Id = 1, Name = "Rice" },
new Product() { Id = 2, Name = 'Corn' }};
ViewData.Add("Products", new SelectList(products, "Id", "Name", ""));
Product product = new Product();
if (Request.IsAjaxRequest())
{
return PartailView("_CreateOrEdit", product)
}
return View("Create", product);
}
_Create view
<%: Html.TextBoxFor(model => model.Quantity) %>
<%: Html.DropDownList("Products") %>
<%: Html.HiddenFieldFor(model => model.Product.Customer.Id) %>

ASP.NET MVC2 model binding problem

Why is my controller receiving an empty model in this case?
Using
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<X.Models.ProductModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h2>Product</h2>
<% using (Html.BeginForm() {%>
<%: Html.ValidationSummary(true) %>
<div class="editor-label">
Product Name
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Name) %>
<%: Html.ValidationMessageFor(model => model.Name) %>
</div>
<br />
<div class="editor-label">
Short Description
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.ShortDesc) %>
<%: Html.ValidationMessageFor(model => model.ShortDesc) %>
</div>
<br />
<div class="editor-label">
Long Description
</div>
<div class="editor-field">
<%: Html.TextAreaFor(model => model.LongDesc) %>
<%: Html.ValidationMessageFor(model => model.LongDesc) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
<% } %>
</asp:Content>
and the following controller.
using System.Web.Mvc;
using X.Lib.Services;
using X.Models;
namespace X.Admin.Controllers
{
public class ProductController : Controller
{
[HttpGet]
public ActionResult ProductData()
{
return View();
}
[HttpPost]
public ActionResult ProductData(ProductModel NewProduct)
{
//Validate and save
if(ModelState.IsValid)
{
//Save And do stuff.
var ProductServ = new ProductService();
ProductServ.AddProduct(NewProduct);
}
return View();
}
}
}
Model:
public class ProductModel
{
public int ID;
[Required(ErrorMessage = "Name is required")]
public string Name;
public string LongDesc;
public string ShortDesc;
}
EDIT: you need to use properties not variables
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
public string LongDesc { get; set; }
public string ShortDesc { get; set; }
Also...
You are not passing the model back to the view.
return View(NewProduct);
I normally pass a blank model in to the GET action too
ProductModel NewProduct = new ProductModel();
return View(NewProduct);
This way if you wish to set any default values you can do so easily.
Code example in full I've also added try and catch blocks around the adding of the product and given example views you could be returning on success or fail:
[HttpGet]
public ActionResult ProductData()
{
ProductModel NewProduct = new ProductModel();
return View(NewProduct);
}
[HttpPost]
public ActionResult ProductData(ProductModel NewProduct)
{
//Validate and save
if(!ModelState.IsValid)
{
// Return the model back to view
return View(NewProduct);
}
try{
//Save And do stuff.
var ProductServ = new ProductService();
ProductServ.AddProduct(NewProduct);
}
catch(Exception){
return View("Fail");
}
return View("Success");
}

Resources