Get Id from Dynamically generated Images in asp.net mvc4 - asp.net-mvc-4

I have some Dynamically Generated images on view using asp.net mvc4...and I have to delete selected
images from from view...but i don't know how to pass id from view to controller
controller code:
public ActionResult imagelist(ShirtDb dg)
{
List<ShirtDb> all = new List<ShirtDb>();
using (patternChangeEntities8 et = new patternChangeEntities8())
{
all = et.ShirtDbs.ToList();
}
return View(all);
}
View Code:
#model List<patternchange.Models.ShirtDb>
#using (Html.BeginForm("Edit", "Patterchange", FormMethod.Post))
{
<table>
#{
int j=0;
for (int i = 0; i < Model.Count(); i += 4) {
j = i;
<tr>
#while(j<i+4&&j<Model.Count())
{
<td>
<img src="data:image/png;base64,#Convert.ToBase64String(Model[j].Image, 0, Model[j].Image.Length)" width="100" onclick="location.href='#Url.Action("Edit", "Patterchange")'" #(Model[j].SId) />
#Html.TextBoxFor(m => Model[j].SId)
<input type="submit" value="delete" />
</td>
j++;
}
<td>
</td>
</tr>
}
}
</table>
}

You can try with below code.in that I have created one JavaScript function which calls when button clicks and I have pass ID in that function at view time.
You can call your controller action via Ajax call
View Code
#model List<patternchange.Models.ShirtDb>
#using (Html.BeginForm("Edit", "Patterchange", FormMethod.Post))
{
<table>
#{
int j=0;
for (int i = 0; i < Model.Count(); i += 4) {
j = i;
<tr>
#while(j<i+4&&j<Model.Count())
{
<td>
<img src="data:image/png;base64,#Convert.ToBase64String(Model[j].Image, 0, Model[j].Image.Length)" width="100" onclick="location.href='#Url.Action("Edit", "Patterchange")'" #(Model[j].SId) />
#Html.TextBoxFor(m => Model[j].SId)
<input type="button" onclick="DeleteImage(#(Model[j].SId))" value="delete" />
</td>
j++;
}
<td>
</td>
</tr>
}
}
</table>
}
Javascript
<script type="text/javascript">
function DeleteImage(ID) {
$.ajax({
type: "POST",
url: '#Url.Action("Edit", "Patterchange")',
contentType: "application/json; charset=utf-8",
data: "{ id: '"+ID+"' }",
dataType: "json",
success: function () { alert('Success'); },
error: function () { alert('error');}
});
}
</script>
Controller code
[HttpPost]
public ActionResult Edit(string id)
{
// Write your code for delete record by using id
return View();
}

Related

Pass Model from Partial View to the PageModel in Asp.Net Core Razor

I am trying to pass a Model from a Partial view back to the PageModel, but the results are always empty. In my main .cshtml, I have an 'Export' button that when clicked opens a bootstrap modal. Users then click a checkbox to select data to download. Here is my code:
In my cs, I set the partial with this code:
// FileContents contains a list of FileObjects (which include Name as IsSelected)
[BindProperty]
public FileContents ExportData { get; set; }
// Get method to return the partial.
// ExportData is passed as the model for the partial
public PartialViewResult OnGetExportModel()
{
ExportData = new FileContents();
ExportData.Files.Add(new FileObject("filename.txt", true);
return Partial("_ExportDetails", ExportData);
}
// Handles postback of the FileContents data
public IActionResult OnPostExportData(FileContents data)
{
//The count is always zero
Console.WriteLine(data.Files.Count);
}
The partial is a table with the file name and a checkbox:
#model FileContents
<div class="form-group">
<table>
<tbody>
#foreach (var item in Model.Files)
{
<tr>
<td class="clsChkBox" data-item="#item.Name">
#Html.CheckBoxFor(modelItem => item.IsSelected)
</td>
<td>#item.Name</td>
</tr>
}
</tbody>
</table>
</div>
In the main page .cshtml, I display the partial:
<div class="dvExport" id="exportPartial"></div>
The partial is set with a class from a script:
function ScriptExport() {
$('.dvExport').load('/index/exportmodel);
}
I have tried several ways to pass the FileContents model of the partial, back to the .cs file.
One by using a <form method=post" asp-page-handler="ExportData" asp-route-data="#Model.ExportData"> . When returned, data.Files is empty.
Second by calling an ajax postback. When serializing #Model.ExportData, the files are also empty.
How can I return FileContents model in the partial back to my main page?
I did a test using ajax, you can refer to my code below:
_ExportDetails.cshtml:
#model FileContents
<div class="form-group">
<table>
<tbody>
#foreach (var item in Model.Files)
{
<tr>
<td class="clsChkBox" data-item="#item.Name">
#Html.CheckBoxFor(modelItem => item.IsSelected)
</td>
//Add a class as an identifier
<td class="Name">#item.Name</td>
</tr>
}
</tbody>
</table>
</div>
Index.cshtml:
#page
#model IndexModel
#{
ViewData["Title"] = "Home page";
}
<button type="button" onclick="ScriptExport()">ScriptExport</button>
<button type="button" onclick="ScriptSubmit()">Submit</button>
<div class="dvExport" id="exportPartial"></div>
//Required
<div>#Html.AntiForgeryToken()</div>
<script>
function ScriptExport() {
$('.dvExport').load('index?handler=ExportModel');
}
function ScriptSubmit(){
var data = [];
$("table > tbody > tr").each(function() {
var Files = {
Name: $(this).find('.Name').text(),
IsSelected: $(this).find("input[type='checkbox']").prop("checked")
}
data.push(Files);
});
$.ajax({
type: "post",
url: "/index?handler=ExportData",
data: JSON.stringify({ Files: data }),
//Required
headers:
{
"RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
},
contentType: "application/json; charset=utf-8",
success: function(result)
{
alert("success");
},
error: function(error)
{
console.log(error);
}
});
}
</script>
Index.cshtml.cs:
public IActionResult OnPostExportData([FromBody]FileContents data)
{
Console.WriteLine(data.Files.Count);
return Page();
}
Test Result:

Razor Page Cascade Datatables by Dropdown

i have a dropdown list and i want to reload the datatable once i change the dropdown please note that the Checkbox field postback the page as well to update the database below is the cs file and will post the cshtml after
public class IndexModel : PageModel
{
private readonly IpponAcademy.Models.IJAContext _context;
public List<SelectListItem> judokaGroupList { get; set; }
[BindProperty]
public Boolean IsAttend { get; set; }
public IList<tbl_Judoka> tbl_Judoka { get;set; }
public IndexModel(IpponAcademy.Models.IJAContext context)
{
_context = context;
}
public void OnGet(Guid? id)
{
var GroupList = _context.LK_Groups.ToList();
judokaGroupList = GroupList.Select(a =>
new SelectListItem
{
Value = a.Group_GUID.ToString(),
Text = a.Group_Name
}).OrderBy(t => t.Text).ToList();
if (id == null)
{
id = Guid.Parse("7F299B82-3397-40F2-8105-65AECB1BA2A8"); //Group A
}
tbl_Judoka = _context.tbl_Judokas.Where(c => c.tbl_Judoka_Groups.Any(o => o.Is_Active == true && o.Group_GUID == id)).Include(c => c.tbl_Judoka_Groups.Where(o => o.Is_Active == true && o.Group_GUID == id)).ToList();
}
public void OnGetJudoka(Guid? id)
{
var GroupList = _context.LK_Groups.ToList();
judokaGroupList = GroupList.Select(a =>
new SelectListItem
{
Value = a.Group_GUID.ToString(),
Text = a.Group_Name
}).OrderBy(t => t.Text).ToList();
if (id == null)
{
id = Guid.Parse("7F299B82-3397-40F2-8105-65AECB1BA2A8"); //Group A
}
tbl_Judoka = _context.tbl_Judokas.Where(c => c.tbl_Judoka_Groups.Any(o => o.Is_Active == true && o.Group_GUID == id)).Include(c => c.tbl_Judoka_Groups.Where(o => o.Is_Active == true && o.Group_GUID == id)).ToList();
}
}
below is the cshtml file, I'd appreciate finding a simple way to do refresh the datatable with the new selected field from the dropdown
#page
#model IpponAcademy.Pages.Attendance.IndexModel
#{
ViewData["Title"] = "Index";
Layout = "~/Pages/Shared/_Layout.cshtml";
}
<form method="post">
<div class="form-group">
<label class="control-label">Group</label>
<select id="ddlGroup" class="form-control" asp-items="Model.judokaGroupList"></select>
#*onchange="alert(#Model.judokaGroupList)"*#
</div>
<table id="taskDt" class="table table-striped table-bordered nowrap" style="width:100%">
<thead>
<tr>
<th>
Attended
</th>
<th>
Code
</th>
<th>
Image
</th>
<th>
Judoka
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.tbl_Judoka)
{
var imagePath = #"UploadedFiles/" + item.J_Image;
<tr>
<td>
<input type="hidden" name="J_GUID" id="J_GUID" value="#item.J_GUID" />
<input asp-for="IsAttend" name="IsAttend" id="IsAttend" type="checkbox" onclick="this.form.submit()" />
</td>
<td>
#Html.DisplayFor(modelItem => item.J_Code)
</td>
<td align="center">
<img src="#imagePath" alt="Judoka" width="50" height="50" class="rounded-circle mr-1" onclick="return LoadDiv(this.src);" style="cursor: pointer" />
</td>
<td>
#Html.DisplayFor(modelItem => item.J_Name)
</td>
</tr>
}
</tbody>
</table>
</form>
#section scripts{
<script>
var table;
function LoadData() {
//alert('in');
table = $("#taskDt").DataTable({
paging: true,
responsive: true,
searching: true,
ordering: true,
order: [[1, "asc"]]
});
}
$(document).ready(function () {
LoadData();
})
$("#ddlGroup").change(function () {
alert('DDLGroup');
//table.ajax.url("/Attendance/Index?handler=GET&Id=" + $("#ddlGroup Option:Selected").val()).load();
window.location.href = '/Attendance/Index?handler=Judoka&Id=' + $("#ddlGroup Option:Selected").val();
});
</script>
}
I think using window.location.href has been a simple enough way to refresh the datatable.Just one thing you need to improve,OnGet and OnGetJudoka method are the same,why not using just one method.
Change:
$("#ddlGroup").change(function () {
window.location.href = '/Attendance/Index?handler=Judoka&Id=' + $("#ddlGroup Option:Selected").val();
});
To:
$("#ddlGroup").change(function () {
window.location.href = '/Attendance/Index?Id=' + $("#ddlGroup Option:Selected").val();
});
If you must use another way,you could use form.submit():
Note:Be sure add name="id",otherwise the parameter will not bind to the backend.
<form method="post" asp-page-handler="Judoka">
<div class="form-group">
<label class="control-label">Group</label>
<select id="ddlGroup" class="form-control" name="id" asp-items="Model.judokaGroupList"
onchange="this.form.submit()"></select>
</div>
</form>
Backend code:
Change:
public void OnGetJudoka(Guid? id)
To:
public void OnPostJudoka(Guid? id)
BTW,I also have a suggestion that you'd better maintain the selected value after postback :
public void OnGetJudoka(Guid? id)
{
var GroupList = _context.LK_Groups.ToList();
judokaGroupList = GroupList.Select(a =>
new SelectListItem
{
Value = a.Group_GUID.ToString(),
Text = a.Group_Name
}).OrderBy(t => t.Text).ToList();
//maintain the selected value after post back...
var selectedValue= judokaGroupList.Where(a => a.Value == id.ToString()).FirstOrDefault();
selectedValue.Selected = true;
//...
}

i am bulding web app the text box that is created in runtime and save data in database asp.net mvc

Here is the code that i am write it is not working well please check my problem an reply as soon as possible
//HomeController.cs
using checkinsert.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace checkinsert.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
List<Table> ci = new List<Table> {new Table {Id=0,name="",contactno=""} };
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(List<Table> ci)
{
if(ModelState.IsValid){
using(Database1Entities dc= new Database1Entities())
{
foreach(var i in ci)
{
dc.Tables.Add(i);
}
dc.SaveChanges();
ViewBag.Message="Data is Successful inserted";
ModelState.Clear();
ci= new List<Table>{new Table{Id=0,name="",contactno=""}};
}
}
return View(ci);
}
}
}
Here is the Index.cshtml and the problem is that text field are not showing in browser means when we run then there is no text field show
And also check the path of jquery file i feel that there is an problem in the path of j query file because j query file is not running ...
#model List<checkinsert.Models.Table>
#{
ViewBag.Title = "Insert Bulk Data";
}
<div style="width:720px;padding:5px;background-color:white;">
#using (Html.BeginForm("Index","Home",FormMethod.Get))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
if(ViewBag.Message!=null)
{
<div style="border:1px solid green">
#ViewBag.Message
</div>
}
<div><a href="#" id="AddNew" >Add New</a></div>
<table id="dataTable" border="0" >
<tr>
<th>Contact Name</th>
<th>Contact No</th>
</tr>
#if (Model != null && Model.Count > 0)
{
int j = 0;
foreach (var i in Model)
{
<tr style="border:1px solid black">
<td>#Html.TextBoxFor(a=>a[j].name)</td>
<td>#Html.TextBoxFor(a=>a[j].contactno)</td>
<td>
#if(j>0)
{
Remove
}
</td>
</tr>
j++;
}
}
</table>
<input type="submit" value="Save Data" />
}
</div>
#* here is the JQuery code *#
#section Scripts {
#Scripts.Render("checkinsert/jquery-3.0.0.min.js")
<script lang="javascript">
$(document).ready(function () {
$("#addNew").click(function () {
e.preventDefault();
var $tablebody = $("#dataTable");
var $trLast = $tablebody.find("tr:last");
var $trNew = $trLast.clone();
var $suffix = $trNew.find(':input:first').attr('name').match(/\d+/);
$trNew.find("td:last").html('Remove');
$.each($trNew.find(':input'), function (i, val) {
// Replaced Name
var $oldN = $(this).attr('name');
var $newN = $oldN.replace('[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']');
$(this).attr('name',nawN);
//Replaced value
var type = $(this).attr('type');
if (type.toLowerCase == "text")
{
$(this).attr('value', '');
// if you have another type then replaced this "text" with default value
$(this).removeClass("input-validation-error");
}
});
$trLast.after($trNew);
// re-assign validation
var form = $("form")
.removeData("validator")
.removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(form);
});
// 2.remove
$('a.remove').live("click", function (e) {
e.preventDefault();
$(this).parent().parent().remove();
});
});
</script>
}
There are two problem in your code
You don't send model after create it in Get
public ActionResult Index()
{
List<Table> ci = new List<Table> {new Table {Id=0,name="",contactno=""} };
return View(ci);
}
foreach in view, you don't need counter you already in for loop.
#if (Model != null && Model.Count > 0)
{
foreach (var tabel in Model)
{
<tr style="border:1px solid black">
<td>#Html.TextBoxFor(a => tabel.name)</td>
<td>#Html.TextBoxFor(a => tabel.contactno)</td>
<td>
Remove
</td>
</tr>
}
}

How do i send the data to edit boxes on the same page?

i have the following page generated
when i click the Edit link, the record data must be sent to the input boxes on teh same page (without refreshing the page)
currently i have the controller code and views
controller: ProductCategory
public class ProductCategoryController : Controller
{
//
// GET: /ProductCategory/
TUDBEntities _db = new TUDBEntities();
public ActionResult Index(string Code)
{
var categories = _db.mt_ProductCategories
.Where(pc => Code == "" || Code == null|| pc.CatCode == Code)
.Select(
c => new ProductCategory {
Id = c.Id,
CategoryCode = c.CatCode,
Name = c.CatName,
Url = c.Url
});
if (Request.IsAjaxRequest())
{
return PartialView("_ProductCategoryList", categories);
}
return View(categories);
}
[HttpPost]
public ActionResult Save(ProductCategory userData)
{
try
{
if (ModelState.IsValid)
{
mt_ProductCategories cat = new mt_ProductCategories { CatCode = userData.CategoryCode, CatName = userData.Name };
// TODO: Add insert logic here
_db.mt_ProductCategories.Add(cat);
_db.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
catch
{
return View();
}
}
public ActionResult Edit(int id)
{
var category = _db.mt_ProductCategories
.Where(pc => pc.Id == id)
.Select(pc => new ProductCategory
{ Id=pc.Id, CategoryCode=pc.CatCode,Name=pc.CatName }).ToList();
return RedirectToAction("Index", category);
}
}
Index view
#model IEnumerable<eComm1.Models.ProductCategory>
#using(Ajax.BeginForm("Save", "ProductCategory",
new AjaxOptions {
HttpMethod="POST",
UpdateTargetId="prod-grid",
InsertionMode=InsertionMode.Replace,
OnSuccess="loaddivdata"
}))
{
<fieldset class="form-group">
<label for="Code">Category Code</label>
<input type="text" class="form-control focus" id="Code" name="CategoryCode" placeholder="Product category code" >
</fieldset>
<fieldset class="form-group">
<label for="ProdName">Product Name</label>
<input type="text" class="form-control" id="ProdName" name="Name" placeholder="Product Name">
</fieldset>
<button type="Submit" class="btn btn-primary">Save</button>
}
<hr />
<div id="prod-grid">
#Html.Partial("_ProductCategoryList", #Model)
</div>
<script type="text/javascript">
$(function () {
$('.focus :input').focus();
});
function loaddivdata() {
$('#prod-grid').html();
$('#Code, #ProdName').val('');
};
// $('#prod-grid').load(function () {
// $.ajax({
// url:'ProductCategoryController/Index',
// method:'GET',
// type:'application/html',
// success: function () { alert('called');}
// });
// });
//});
</script>
Partial View: _ProductCategoryList
#model IEnumerable<eComm1.Models.ProductCategory>
<div class="panel panel-default">
#if (Model.Count() == 0) { <div class="panel-heading">Product Categories - <span style='color:red;font-weight:bold' >0 RESULTS FOUND</span></div>
}else{
<!-- Default panel contents -->
<div class="panel-heading">Product Categories</div>
}
<!-- Table -->
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.CategoryCode)
</th>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Url)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CategoryCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Url)
</td>
<td>
#*#Html.beActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Details", "Details", new { id=item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.Id })*#
#Ajax.ActionLink("Edit", "Edit", "ProductCategory", new { id=item.Id}, new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "", OnSuccess = "loadformdata" }) |
#Ajax.ActionLink("Delete", "Delete", "ProductCategory", new { id=item.Id}, new AjaxOptions{ HttpMethod="POST", UpdateTargetId="", OnSuccess="loadformdata"})
</td>
</tr>
}
</table>
</div>
How do i modify my code to send data those input control and in my code how do i create hidden field for Id value so it can be send to the Edit(collection, int id) action to update the record?
for Stephen Muecke, i have added my jquery files through the bundles
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/ecomm").Include(
"~/Scripts/jquery-{version}.js",
"~/Scripts/jquery-2.1.4.min.js",
"~/Scripts/bootstrap.js",
"~/Scripts/bootstrap.min.js",
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/jquery.validate*"
));
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
"~/Scripts/jquery-ui-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/jquery.validate*"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.min.css",
"~/Content/bootstrap.css",
"~/Content/style.css"));
bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
"~/Content/themes/base/jquery.ui.core.css",
"~/Content/themes/base/jquery.ui.resizable.css",
"~/Content/themes/base/jquery.ui.selectable.css",
"~/Content/themes/base/jquery.ui.accordion.css",
"~/Content/themes/base/jquery.ui.autocomplete.css",
"~/Content/themes/base/jquery.ui.button.css",
"~/Content/themes/base/jquery.ui.dialog.css",
"~/Content/themes/base/jquery.ui.slider.css",
"~/Content/themes/base/jquery.ui.tabs.css",
"~/Content/themes/base/jquery.ui.datepicker.css",
"~/Content/themes/base/jquery.ui.progressbar.css",
"~/Content/themes/base/jquery.ui.theme.css"));
}
In the partial view
#Ajax.ActionLink("Edit", "Edit", "ProductCategory", new { id = item.Id }, new AjaxOptions { HttpMethod = "GET", OnSuccess = "loadformdata" }) |
#Ajax.ActionLink("Delete", "Delete", "ProductCategory", new { id=item.Id}, new AjaxOptions{ HttpMethod="POST", OnSuccess="loadformdata"})
in the index view the following js function:
function loadformdata() {
var cells = $(this).closest('tr').children('td');
alert(cells.eq(0).text());
//$('#Code').val(cells.eq(0).text());
//$('#ProdName').val(cells.eq(1).text());
}
To: Stephen Muecke:
i have removed above loadformdata() and put everything as you said. this youtube video shows the problem that still does not call that click event
To: Steven Meucke:
there's still no luck, for ease i have added a alert() in the function and the alert() won't show. Here is the video
Give you 'Edit' link a class name (say) class="edit" and handle its .click() event to update the form controls
$('.edit').click(function() {
var cells = $(this).closest('tr').children('td');
$('#Code').val(cells.eq(0).text());
$('#ProdName').val(cells.eq(1).text());
return false; // cancel the default redirect
});
Side note: You could just replace the ActionLink() code with Edit and the return false; line is not necessary.
write script for ajax call:
$('#edit').click(function () {
// var data = {here you will pass item.id }
$.ajax({
url:'ProductCategoryController/Edit',
data: {id : data}
method:'GET',
success: function (data) {
//clear html page here
//reload html page by passing 'data' passes in function
//e.g. suppose html page id is 'xyz' then $("#xyz").html(data)
}
});
});

POSt method for AJAX dynamically created input fields

I am using MVC and razor.
I have sucessfully implemented a way for the user to dynamically add more input rows at a click of a button (using AJAX and following Steven Sanderson's blog). BUT I do not know how to save the data to a database that the user inputs in these dynamically created fields.
I use his helper class, that quite frankly I am struggling to understand at all.
My question is what do I need to put in the POST create method. The link to the code in his blog is here:
steven sanderson's blog
Just a pointer in the right direction is all I need. THis is my current code:
New row partial view:
#model ef_tut.ViewModels.ClaimsViewModel
#using ef_tut.WebUI.Helpers
#using (Html.BeginCollectionItem("claims"))
{
<table class="editorRow">
<tr >
<td>
SubmissionUserID: #Html. EditorFor (o.claim.SubmissionUserID)
</td>
<td>
ClaimID: #Html.EditorFor(o => o.claim.ClaimID)
</td>
<td>
#Html.EditorFor(o => o.claim.ApprovedYN)
</td>
<td>
ClaimID(claimlinetable)#Html.EditorFor(o => o.claimline.ClaimID)
</td>
<td>
ClaimantUserID: #Html.EditorFor(o => o.claimline.ClaimantUserID)
</td>
<td>
Hours: #Html.EditorFor(o => o.claimline.Hours)
</td>
<td>
MileageCost: #Html.EditorFor(o => o.claimline.MileageCost)
</td>
<td>
TravelCost: #Html.EditorFor(o => o.claimline.TravelCost)
</td>
<td>
Hours cost: #Html.EditorFor(o => o.claimline.HoursCost)
</td>
<td>
Total cost: #Html.EditorFor(o => o.claimline.TotalCost)
</td>
<td>
ProxyYN: #Html.EditorFor(o => o.claimline.ProxyClaim)
</td>
<td>
CatID: #Html.EditorFor(o => o.claimline.CatID)
</td>
<td>
SubCatID: #Html.EditorFor(o => o.claimline.SubCatID)
</td>
<td>
delete
</td>
</tr></table>
}
Blankeditorrowmethod
public PartialViewResult BlankEditorRow()
{
return PartialView("NewRow", new ClaimsViewModel());
}
My current POST method that creates new DB records but all fields are null
[HttpPost]
public ActionResult Create(ClaimsViewModel viewModel)
{
if (ModelState.IsValid)
{
db.claims.Add(viewModel.claim);
db.claimlines.Add(viewModel.claimline);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
Create view
#model ef_tut.ViewModels.ClaimsViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>claim</legend>
<div id="editorRows"></div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Add another...", "BlankEditorRow", null, new { id = "addItem" })
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
jquery
$("#addItem").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) { $("#editorRows").append(html); }
});
return false;
});
$("a.deleteRow").live("click", function () {
$(this).parents("table.editorRow:first").remove();
return false;
});
Steven's helper
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
namespace ef_tut.WebUI.Helpers
{
public static class HtmlPrefixScopeExtensions
{
private const string idsToReuseKey = "__htmlPrefixScopeExtensions_IdsToReuse_";
public static IDisposable BeginCollectionItem(this HtmlHelper html, string collectionName)
{
var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName);
string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : Guid.NewGuid().ToString();
html.ViewContext.Writer.WriteLine(string.Format("<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />", collectionName, html.Encode(itemIndex)));
return BeginHtmlFieldPrefixScope(html, string.Format("{0}[{1}]", collectionName, itemIndex));
}
public static IDisposable BeginHtmlFieldPrefixScope(this HtmlHelper html, string htmlFieldPrefix)
{
return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo, htmlFieldPrefix);
}
private static Queue<string> GetIdsToReuse(HttpContextBase httpContext, string collectionName)
{
string key = idsToReuseKey + collectionName;
var queue = (Queue<string>)httpContext.Items[key];
if (queue == null)
{
httpContext.Items[key] = queue = new Queue<string>();
var previouslyUsedIds = httpContext.Request[collectionName + ".index"];
if (!string.IsNullOrEmpty(previouslyUsedIds))
foreach (string previouslyUsedId in previouslyUsedIds.Split(','))
queue.Enqueue(previouslyUsedId);
}
return queue;
}
private class HtmlFieldPrefixScope : IDisposable
{
private readonly TemplateInfo templateInfo;
private readonly string previousHtmlFieldPrefix;
public HtmlFieldPrefixScope(TemplateInfo templateInfo, string htmlFieldPrefix)
{
this.templateInfo = templateInfo;
previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix;
templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
}
public void Dispose()
{
templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix;
}
}
}
}
Use FormCollection, so instead of this:
[HttpPost]
public ActionResult Create(ClaimsViewModel viewModel)
{
}
You will have this:
[HttpPost]
public ActionResult Create(FormCollection formCollection)
{
}
You should be able to get the value for any new fields you have created using their name like so:
var newFieldValue = formCollection["newFieldName"];