Post mvc3 table to controller action - asp.net-mvc-3

I have a simple table
#using (Html.BeginForm("Save", "Subscription", FormMethod.Post))
{
<table>
<tr>
<th>
Name
</th>
<th>
Report
</th>
</tr>
#foreach (var item in Model.ReportSubscriptions)
{
<tr>
<td>
#Html.HiddenFor(item.Id)
#Html.TextBoxFor(item.Name)
</td>
<td>
#Html.TextBoxFor(item.Report)
</td>
</tr>
}
</table>
<button type="submit">Save</button>
}
The save action
public ViewResult Save(IEnumerable<ReportSubscription> list)
{
throw new NotImplementedException();
}
}
How can I get MVC to deserialize the post back to my model?

For collections you need to do a Editor template and use
#Html.EditorFor(m => m.Collection);

Related

How to display Company in header in asp.net mvc 3

I have this view :
model IEnumerable<MvcApplication4.Models.Order>
#{
ViewBag.Title = "Index";
}
<h2>
display CompanyName
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Customer
</th>
<th>
EmployeeID
</th>
<th>
OrderDate
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Customer.CompanyName)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmployeeID)
</td>
<td>
#Html.DisplayFor(modelItem => item.OrderDate)
</td>
</tr>
}
</table>
I want to display the CompanyName where I marked in bold. At the moment its being displayed in the foreach loop. However I want that one field which is same for this view to pull the CompanyName and display it in between my headings.
How about putting
#{
if (Model.Any()) {
Model.First().Customer.CompanyName
}
}
where your bold text is?

HTTP POST, GET in MVC?

In MVC3, i created one register form. I created one model,,controller and view. This is my code:
[HttpGet]
public ActionResult Insert()
{
Models.Employees objEmpl = new Models.Employees();
return View(objEmpl);
}
[HttpPost]
[AcceptVerbs("Post")]
public ActionResult Insert(Models.Employees objs)
{
var v = new Models.test().InsertDl(objs);
return View();
}
The above is my controller
#model MvcVideo.Models.Employees
#{
ViewBag.Title = "Insert";
Layout = "~/Views/Shared/VideoLayout.cshtml";
}
<h2>Insert</h2>
#using(Html.BeginForm("Insert","Home",FormMethod.Post ))
{
<table>
<tr>
<td>
Employee Name
</td>
<td>
#Html.TextBox("Ename",#Model.Enames)
</td>
</tr>
<tr>
<td>
Department Id
</td>
<td>
#Html.TextBox("Departmentid",#Model.DepartId )
</td>
</tr>
<tr>
<td>
Email Id
</td>
<td>
#Html.TextBox("Emailid",#Model.EmailIds)
</td>
</tr>
<tr>
<td>
Address
</td>
<td>
#Html.TextBox("Address",#Model.Adress)
</td>
</tr>
<tr>
<td colspan="2" style="text-align:center;" >
<button title ="Ok" value="OK"></button>
</td>
</tr>
</table>
}
But the objs object at public actionresult Insert(models.Empoyees objs) action method parameter is showing null values. Imean Ename=Null, Department=0, Emailid=Null and Address=null
It isn't working because the names you've provided in your Html helpers don't match up with the property names on your model, so the default model binder can't resolve them when the values get posted back.
Using Html.TextBoxFor instead of Html.TextBox will provide you with strong typing against your model, and is the safer approach.
Replace this
#Html.TextBox("Ename",#Model.Enames)
With
#Html.TextBoxFor(model => model.Enames)
This will fix your issue.

Updating multiple items within same view

I am trying to make a stock take application, My view loads all my stock with one editor.
My controller is not getting any of the data from the view?
I want to be able to edit all my stock at the same time?
How can I do this
Model Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace FlatSystem.Models
{
public class Stock
{
public int ID { get; set; }
public string Item_Name { get; set; }
public int Actual_Stock { get; set; }
public int Wanted_Stock { get; set; }
}
}
View Code
#model IEnumerable<FlatSystem.Models.Stock>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<div class="sidemenu">
<div class="sidemenu-heading">
ReStock
</div>
<div class="div-body">
<table>
<tr>
<th>
Item Name
</th>
<th>
Wanted Stock
</th>
<th>
Stock On Hand
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Item_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Wanted_Stock)
</td>
<td>
<div class="editor-field">
#Html.EditorFor(modelItem => item.Actual_Stock)
#Html.ValidationMessageFor(modelItem => item.Actual_Stock)
</div>
</td>
#Html.HiddenFor(modelItem => item.ID)
</tr>
}
</table>
</div>
</div>
<input type="submit" value="Submit" />
}
Controller Code
[HttpPost]
public ActionResult ReStock(List<Stock> stock)
{
foreach (var item in stock)
{
if (ModelState.IsValid)
{
GR.InsertOrUpdate(item);
}
}
GR.Save();
return RedirectToAction("Restock");
}
It's hard to answer your question without model class, but idea is that your edit inputs must contain index in name attribute.
Something like this:
#for(int i = 0: i < Model.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => Model[i].Item_Name)
</td>
<td>
#Html.DisplayFor(modelItem => Model[i].Wanted_Stock)
</td>
<td>
<div class="editor-field">
#Html.EditorFor(modelItem => Model[i].Actual_Stock)
#Html.ValidationMessageFor(modelItem => Model[i].Actual_Stock)
</div>
</td>
#Html.HiddenFor(modelItem => Model[i].ID)
</tr>
}
Added:
Sorry, thanks to Darin Dimitrov, you can't access IEnumerable by index, use List or Array.
You could use editor templates. I would recommend you to first read the following article in order to understand why your code doesn't correctly bind the collection. Once you understand that you could do the following:
#model IEnumerable<FlatSystem.Models.Stock>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<div class="sidemenu">
<div class="sidemenu-heading">
ReStock
</div>
<div class="div-body">
<table>
<thead>
<tr>
<th>Item Name</th>
<th>Wanted Stock</th>
<th>Stock On Hand</th>
<th></th>
</tr>
</thead>
<tbody>
#Html.EditorForModel()
</tbody>
</div>
</div>
<input type="submit" value="Submit" />
}
and now define a custom editor template for the Stock type which will automatically be rendered for each element of the collection (~/Views/Shared/EditorTemplates/Stock.cshtml) - the name and location of the editor template is important as it works by convention:
#model FlatSystem.Models.Stock
<tr>
<td>
#Html.DisplayFor(x => x.Item_Name)
</td>
<td>
#Html.DisplayFor(x => x.Wanted_Stock)
</td>
<td>
<div class="editor-field">
#Html.EditorFor(x => x.Actual_Stock)
#Html.ValidationMessageFor(x => x.Actual_Stock)
</div>
</td>
#Html.HiddenFor(x => x.ID)
</tr>
Remark: You might also want to include the Wanted_Stock and Item_Name as hidden fields along with the ID in the editor template in order for their values to be sent to the server, because you don't have a corresponding input field for them.

How to do a bulk persist on a partial view?

I have written a partial view that displays a list of rows, where some fields in the row are editable using a textbox, checkbox, or whatever.
I would like the parent view to have a "submit" button that posts the whole collection of updated rows so that I can do a group update rather than posting once for every updated row.
Here's what I have:
public class GroupModel {
public string SomeGenericProperty { get; set; }
public IEnumerable<ItemModel> Items { get; set; }
}
public class ItemModel {
public long ID { get; set; }
public string Field1 { get; set; }
public string Field2 { get; set; }
}
Then I have a view "GroupDetails":
#model MyNamespace.GroupModel
...
#using (Html.BeginForm("SaveItems", "Home")) {
<fieldset>
...
#Html.Partial("ItemList", Model.Items)
...
<input type="submit" value="Approve" />
</fieldset>
}
And a partial view "ItemList":
#model IEnumerable<MyNamespace.ItemModel>
<table>
<tr>
<th>
Field 1
</th>
<th>
Field 2
</th>
<th>
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.TextBoxFor(modelItem => item.Field1)
</td>
<td>
#Html.TextBoxFor(modelItem => item.Field2)
</td>
<td>
#Html.HiddenFor(i => item.ID)
</td>
</tr>
}
</table>
But when I post, the information from partial view is not being posted; the GroupModel object's Items property is null.
What's the right way to do this?
I would recommend you to always use editor templates. The reason your code doesn't work is because you used a partial and this partial doesn't inherit the parent template context which means that helpers that are used inside it will generate wrong names for the input fields.
For example if you look at the source code of your page you will see this:
<td>
<input type="text" name="[0].Field1" id="[0]_Field1" />
</td>
instead of the correct name which is:
<td>
<input type="text" name="Items[0].Field1" id="Items[0]_Field1" />
</td>
I would recommend you reading the following blog post to better understand the wire format that the default model binder expects.
So start by fixing your main view first and replace the partial with an editor template:
#model MyNamespace.GroupModel
#using (Html.BeginForm("SaveItems", "Home"))
{
<fieldset>
...
<table>
<thead>
<tr>
<th> Field 1 </th>
<th> Field 2 </th>
<th></th>
</tr>
</thead>
<tbody>
#Html.EditorFor(x => x.Items)
</tbody>
</table>
...
<input type="submit" value="Approve" />
</fieldset>
}
and then define a custom editor template that will be rendered for each element of the model (~/Views/Shared/EditorTemplates/ItemModel.cshtml - this works by convention, it should be either inside ~/Views/Shared/EditorTemplates if you want it to be reused among controllers or inside ~/Views/Home/EditorTemplates if you want this template to be available only for the Home controller - and the name of the template must be the type of the collection - in your case it is ItemModel.cshtml):
#model MyNamespace.ItemModel
<tr>
<td>
#Html.TextBoxFor(x => x.Field1)
</td>
<td>
#Html.TextBoxFor(x => x.Field2)
</td>
<td>
#Html.HiddenFor(x => x.ID)
</td>
</tr>
Now everything will bind fine and dandy in your controller action:
[HttpPost]
public ActionResult SaveItems(GroupModel model)
{
...
}

Paging in a scaffolding view MVC3

so using EF4 I create a scaffolding controller/view, so my question is how can I Add Paging to my view in easy/fast way??
the
controller generated
public ViewResult Index()
{
return View(db.Perifericos.ToList());
}
the
view: generated
#model IEnumerable<Paginacion.Models.Perifericos>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Nombre
</th>
<th>
Modelo
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Nombre)
</td>
<td>
#Html.DisplayFor(modelItem => item.Modelo)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.idPerifericos }) |
#Html.ActionLink("Delete", "Delete", new { id=item.idPerifericos })
</td>
</tr>
}
</table>
Maybe this can help you: http://www.asp.net/entity-framework/tutorials/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application
You have to implement a paging in controller and in the view add code like the link that i have given to you.
I use this one http://blogs.taiga.nl/martijn/2008/08/27/paging-with-aspnet-mvc/
It's support also ajax and areas
Easy to implement.
a complete msdn article with sample code
Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application

Resources