Details View is displaying “System.Data.Entity.DynamicProxies - asp.net-mvc-4

I dont know how to solve the proble, something is wrong, please help!
the problem is:
The model item passed into the dictionary is of type 'System.Data.Entity.DynamicProxies.Student_0C394DD28745C7061A0EB9964A9FAD1A77E5EB1B24F61D61E2229472BCC850EE', but this dictionary requires a model item of type 'ContosoUniversity.ViewModels.DetailsViewModel'.
StudentController:
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = _db.Students.Include(m => m.Comments).SingleOrDefault(x => x.ID == id);
if (student == null)
{
return HttpNotFound();
}
var model = new DetailsViewModel
{
Comment = new Comment(),
Student = student,
Comments = student.Comments.OrderBy(c => c.Id).ToList()
};
return View(student);
}
View:
#model ContosoUniversity.ViewModels.DetailsViewModel
#{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<div>
<h4>Student</h4>
<hr />
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.Student.LastName)
</dt>
<dd>
#Html.DisplayFor(model => model.Student.LastName)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Student.FirstMidName)
</dt>
<dd>
#Html.DisplayFor(model => model.Student.FirstMidName)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Student.EnrollmentDate)
</dt>
<dd>
#Html.DisplayFor(model => model.Student.EnrollmentDate)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Student.Enrollments)
</dt>
<dd>
<table class="table">
<tr>
<th>Course Title</th>
<th>Grade</th>
</tr>
#foreach (var item in Model.Enrollments)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Course.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
</dd>
</dl>
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
#Html.ValidationSummary(true)
<input type="hidden" value="#Model.Comment.Id" name="commentId" />
<div class="form-group">
#Html.LabelFor(model => model.Comment.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Comment.Name)
#Html.ValidationMessageFor(model => model.Comment.Name)
</div>
</div>
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Comment.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Comment.Email)
#Html.ValidationMessageFor(model => model.Comment.Email)
</div>
</div>
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Comment.Text, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Comment.Text)
#Html.ValidationMessageFor(model => model.Comment.Text)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div id="comments">
#foreach (var c in Model.Comments)
{
#Html.Partial("_Comment", c)
}
</div>
</div>
<p>
#Html.ActionLink("Edit", "Edit", new { id = Model.Student.ID }) |
#Html.ActionLink("Back to List", "Index")
</p>
DetailsViewModel:
public Student Student { get; set; }
public List<Comment> Comments { get; set; }
public Comment Comment { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
Comment model:
public int Id { get; set; }
public int CommentId { get; set; }
public Student Student { get; set; }
[Required]
public string Name { get; set; }
[EmailAddress]
public string Email { get; set; }
[Required]
public string Text { get; set; }
Student Model:
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public string FullName
{
get
{
return string.Join(" ", FirstMidName, LastName);
}
}
public virtual ICollection<Enrollment> Enrollments { get; set; }
public List<Comment> Comments { get; set; }
if somebody didnt understand Im trying add commentaries list at Details page with partial view.

You are trying to pass a Student Object to the View where you defined waht object it will handle Namely: #model ContosoUniversity.ViewModels.DetailsViewModel
You need to either in your controller pass the view a DetailsViewModel or you have to rethink what you are doing/ need to do, and make the view handle object Student.
i dont know where this model is but something like:
#model ContosoUniversity.Models.Student

Assuming you have a DisplayTemplates folder in your Shared Views folder named _Comment.cshtml (i.e. a path like /Views/Shared/DisplayTemplates/_Comment.cshtml) you should try the following:
Rename _Comment.cshtml to Comment.cshtml
Replace the following:
<div id="comments">
#foreach (var c in Model.Comments)
{
#Html.Partial("_Comment", c)
}
</div>
with the following:
#Html.DisplayFor(model => model.Comments)
I just fought with this myself and the underscore in the filename was what was breaking things.

Related

Rating system how can I transfer my rating value (0-5) into width %

I have a rating system with CRUD api. The rating value is int 0-5 I would love to show the stars instead of the figure in the standard razor template.
I looked up the demo CSS for star ratings via FontAwesome
However the value in width is not filling the colors and white and empty stars are wrapped.
In addition how can I write my value in int to a % value
==== Here is my detail page ====
#page
#using Microsoft.AspNetCore.Localization
#using Microsoft.AspNetCore.Mvc.Localization
#model WorkCollaboration.Pages.RatingfromCusContactOverview.DetailsModel
#{
ViewData["Title"] = "Details";
}
#inject IViewLocalizer Localizer
<h1>#Localizer["Details"]</h1>
<div>
<h4>#Localizer["RatingsfromCusContactOverview"]</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.RatingDate)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.RatingDate)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.RatingSupContactId)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.RatingSupContactId)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.RatingTitle)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.RatingTitle)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.RatingValue)
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet" />
<span class="score">
<div class="score-wrap">
<span class="stars-active" style="width:50%">
<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
</span>
<span class="stars-inactive">
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star-o" aria-hidden="true"></i>
</span>
</div>
</span>
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.RatingValue)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.RatingText)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.RatingText)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.RatingReviewed)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.RatingReviewed)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.CusContactId)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.CusContactId)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.CusContactFirstName)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.CusContactFirstName)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.CusContactLastName)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.CusContactLastName)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.SupContactId)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.SupContactId)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.SupContactFirstName)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.SupContactFirstName)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.RatingfromCusContactOverview.SupContactLastName)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.RatingfromCusContactOverview.SupContactLastName)
</dd>
</dl>
</div>
<div>
<a asp-page="/RatingfromCusContactToSupContact/Edit" asp-route-id="#Model.RatingfromCusContactOverview.RatingId">#Localizer["Edit"]</a>
<a asp-page="/RatingfromCusContactOverview/Index">#Localizer["Back to List"]</a>
</div>
=== Here is my c# code ======
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using WorkCollaboration.Data;
using WorkCollaboration.Models;
namespace WorkCollaboration.Pages.RatingfromCusContactOverview
{
public class DetailsModel : PageModel
{
private readonly WorkCollaboration.Data.WorkCollaborationContext _context;
public DetailsModel(WorkCollaboration.Data.WorkCollaborationContext context)
{
_context = context;
}
public Models.RatingfromCusContactOverview RatingfromCusContactOverview { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
RatingfromCusContactOverview = await _context.RatingfromCusContactOverview.FirstOrDefaultAsync(m => m.RatingId == id);
if (RatingfromCusContactOverview == null)
{
return NotFound();
}
return Page();
}
}
}
===== Here is my model =====
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace WorkCollaboration.Models
{
public class RatingfromCusContactOverview
{
[Key]
[Display(Name = "Rating Id"), Required(ErrorMessage = "Rating Id Required")]
public int RatingId { get; set; }
[Display(Name = "Customer Contact Id"), Required(ErrorMessage = "Customer Contact Id Required")]
public int RatingCusContactId { get; set; }
[Display(Name = "Date"), Required(ErrorMessage = "Date Required")]
public DateTime RatingDate { get; set; }
[Display(Name = "Supplier Contact Id"), Required(ErrorMessage = "Supplier Contact Id Required")]
public int RatingSupContactId { get; set; }
[Display(Name = "Title"), Required(ErrorMessage = "Title Required")]
public string RatingTitle { get; set; }
[Display(Name = "Rating Value"), Required(ErrorMessage = "Rating Value Required")]
public int RatingValue { get; set; }
[Display(Name = "Rating Text")]
public string RatingText { get; set; }
[Display(Name = "Rating Reviewed Contact Id"), Required(ErrorMessage = "Rating Reviewed Required")]
public int RatingReviewed { get; set; }
[Display(Name = "Customer Contact Id")]
public int CusContactId { get; set; }
[Display(Name = "Customer Contact First Name")]
public string CusContactFirstName { get; set; }
[Display(Name = "Customer Contact Last Name")]
public string CusContactLastName { get; set; }
[Display(Name = "Supplier Contact Id")]
public int SupContactId { get; set; }
[Display(Name = "Supplier Contact First Name")]
public string SupContactFirstName { get; set; }
[Display(Name = "Supplier Contact First Name")]
public string SupContactLastName { get; set; }
}
}
It looks like this
!Attached picture shows how it looks when it runs
Thanks for helping
Do you mean that you want display the the stars rate and a percent value from a int value?
Index.cshtml.cs:
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
[Display(Name = "Rating Value"), Required(ErrorMessage = "Rating Value Required")]
public int RatingValue { get; set; }
public void OnGet()
{
RatingValue = 2;
}
public void OnPost()
{
}
}
Index.cshtml:
#page
#model IndexModel
#{
ViewData["Title"] = "Home page";
}
<style>
i {
color: #EEBD01;
}
</style>
#Html.DisplayNameFor(model => model.RatingValue)
<div>
<span class="start_rate">
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star-o" aria-hidden="true"></i>
<i class="fa fa-star-o" aria-hidden="true"></i>
</span>
</div>
<div id="percent">
</div>
#section scripts{
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet" />
<script>
$(function () {
var ratingValue = #Html.Raw(Model.RatingValue);
var startlist = $('.start_rate').children();
for (var i = 0; i < ratingValue; i++) {
startlist[i].classList.remove('fa-star-o');
startlist[i].classList.add('fa-star');
}
$('#percent').html(ratingValue/5 * 100 + "%")
})
</script>
}
Result:

Using JavaScript code behind asp.net core c#

I want to use sweet alert with asp.net core c#. To replace my alert system. However I need some guidance.
When I am on a controller say edit and just after the save I want to excute this javascript what is my best way in .net core in web forms days we had registerscript.
I also need to show this message when I create a record
https://sweetalert2.github.io/
swal({
title: "MIS",
text: "Case Created your Case Number is ",
icon: "warning",
buttons: true,
dangerMode: true,
})
1.If you want to alert after save successfully,follow this:
Model:
public class Test
{
public int Id { get; set; }
public string Name { get; set; }
}
Index.cshtml:
#model IEnumerable<Test>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
#section Scripts
{
#if (TempData["notification"] != null)
{
#Html.Raw(TempData["notification"])
}
}
Edit.cshtml:
#model Test
<h4>Test</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Controller:
public class TestsController : Controller
{
private readonly Mvc3_1Context _context;
public TestsController(Mvc3_1Context context)
{
_context = context;
}
public void Alert(int id)
{
var msg = "<script language='javascript'>swal({title: 'MIS',text: 'Case Created your Case Number is "+id+"', icon: 'warning',buttons: true,dangerMode: true})" + "</script>";
TempData["notification"] = msg;
}
// GET: Tests
public async Task<IActionResult> Index()
{
return View(await _context.Test.ToListAsync());
}
// GET: Tests/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var test = await _context.Test.FindAsync(id);
if (test == null)
{
return NotFound();
}
return View(test);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, Test test)
{
if (id != test.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
_context.Update(test);
await _context.SaveChangesAsync();
Alert(id);//add this method
return RedirectToAction(nameof(Index));
}
return View(test);
}
}
_Layout.cshtml:
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
//add this line
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
Result:
2.If you want to alert before save sucessfully:
Model:
Same as the option one.
Index.cshtml:
#model IEnumerable<Test>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Edit.cshtml:
#model Test
<h4>Test</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<input type="button" value="Save" class="btn btn-primary" onclick="confirmEdit()"/>
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
<script>
function confirmEdit() {
swal({
title: "MIS",
text: "Case Created your Case Number is " + $("#Id").val(),
icon: "warning",
buttons: true,
dangerMode: true,
}).then((willUpdate) => {
if (willUpdate) {
$.ajax({
url: "/tests/edit/"+$("#Id").val(),
type: "POST",
data: {
Id: $("#Id").val(),
Name:$("#Name").val()
},
dataType: "html",
success: function () {
swal("Done!", "It was succesfully edited!", "success")
.then((success) => {
window.location.href="/tests/index"
});
},
error: function (xhr, ajaxOptions, thrownError) {
swal("Error updating!", "Please try again", "error");
}
});
}
});
}
</script>
}
Controller:
public class TestsController : Controller
{
private readonly Mvc3_1Context _context;
public TestsController(Mvc3_1Context context)
{
_context = context;
}
// GET: Tests
public async Task<IActionResult> Index()
{
return View(await _context.Test.ToListAsync());
}
// GET: Tests/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var test = await _context.Test.FindAsync(id);
if (test == null)
{
return NotFound();
}
return View(test);
}
[HttpPost]
public async Task<IActionResult> Edit(int id, [FromForm]Test test)
{
if (id != test.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
_context.Update(test);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(test);
}
}
_Layout.cshtml:
Same as option one.
Result:
I had to use AJAX on my .NETCORE 3.1 application to implement the Sweet Alert 2.
The syntax is just a little different than yours.
Documentation for Sweet Alert 2 can be found on this link.
A simple example, say you want an early on a button click, you could do something like:
HTML:
<input id="btnSubmit" type="button" class="btn btn-success btn-block" value="Submit" />
jQuery:
<script type="text/javascript">
$(document).ready(function () {
$("#btnSubmit").click(function () {
Swal.fire({
title: 'MIS',
text: "Case Created your Case Number is",
icon: 'error',
confirmButtonText: 'Ok'
})
});
});
</script>
Also, don't forget to add your sweetalert script tags:
<script src="~/filepath/sweetalert2.min.js"></script>

HiddenFor value is empty

I have a view
#using (#Html.BeginForm())
{
<div class="form-horizontal">
<h4>Person</h4>
<hr/>
#Html.ValidationSummary(true)
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
#Html.HiddenFor(x => x.PersonId)
</div>
<div class="form-group">
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
</div>
<div class="form-group">
#Html.LabelFor(m => m.Gender)
#Html.DropDownListFor(m => m.Gender, Html.GetEnumSelectList(typeof(Gender)))
#Html.ValidationMessageFor(m => m.Gender)
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default"/>
</div>
</div>
</div>
}
And ViewModel
public class Person
{
[HiddenInput]
public int PersonId { get; set; }
[Required]
public string Name { get; set; }
public Gender Gender { get; set; }
}
public enum Gender
{
Male,
Female
}
The problem is validation complaints about PersonId being null.
It renders in browser as such (see, value is empty, but should be zero).
<div class="form-group">
<input data-val="true" data-val-required="The PersonId field is required." id="PersonId" name="PersonId" value="" type="hidden">
</div>
Could you please help? I'm using ASP.NET Core 1.8 RC2
Maybe you don't initialize object (Person) so the value is empty.
You could do as below then the value will not be empty.

Updating multiple list items within same view

I am trying to make a default value take application, My view loads all my value with one editor. My controller is not getting any of the data from the view?
I want to be able to edit all my value at the same time? How can I do this
Model Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Demo.Models.Admin
{
public class MerchantPackageTransactionModel
{
public MerchantPackageTransactionModel()
{
FeatureList = new List<PackageFeatureModel>();
}
public int PackageId { get; set; }
public string PackageName { get; set; }
public string Image { get; set; }
public List<PackageFeatureModel> FeatureList { get; set; }
}
public class PackageFeatureModel
{
public int FeatureId { get; set; }
public string FeatureName { get; set; }
public string Type { get; set; }
public string DefaultValue { get; set; }
public string Value { get; set; }
}
}
View Code
#model Demo.Models.Admin.MerchantPackageTransactionModel
#{
ViewBag.Title = "CreatePackageTransaction";
Layout = "~/Themes/green/Views/Shared/_AdminDashboard.cshtml";
}
#using (Html.BeginForm())
{
<fieldset>
<legend>MerchantPackageTransactionModel</legend>
#Html.HiddenFor(model => model.PackageId)
<div class="editor-label">
#Html.LabelFor(model => model.PackageName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PackageName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Image)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Image)
</div>
#foreach (var item in Model.FeatureList)
{
#Html.HiddenFor(model => item.FeatureId)
<div class="editor-label">
#Html.Label("Feature Name")
</div>
<div class="editor-field">
#Html.DisplayFor(model => item.FeatureName)
</div>
<div class="editor-label">
#Html.Label("Type")
</div>
<div class="editor-field">
#Html.DisplayFor(model => item.Type)
</div>
<div class="editor-label">
#Html.Label("Default Value")
</div>
<div class="editor-field">
#Html.DisplayFor(model => item.DefaultValue)
</div>
<div class="editor-label">
#Html.Label("Value")
</div>
<div class="editor-field">
#Html.EditorFor(model => item.Value)
</div>
}
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Controller code
public ActionResult CreatePackageTransaction(MerchantPackageTransactionModel objMerchantPackageTransactionModel)
{
foreach (var item in objMerchantPackageTransactionModel.FeatureList)
{
if (ModelState.IsValid)
{
GR.InsertOrUpdate(item);
}
}
GR.Save();
return View(objMerchantPackageTransactionModel);
}
What is happening is, because you are using
#Html.EditorFor(model => item.Value)
that is a command directly associated with the model and it is being used to render an input not accessed from the model (item), it is rendering an input html with the "wrong" name:
<input class="text-box single-line" id="item_Value" name="item.Value" type="text" value="">
when it should be
<input class="text-box single-line" id="FeatureList_0__Value" name="FeatureList[0].Value" type="text" value="">
And, as name does not match with the one from the model (FeatureList), the framework cannot do the automatic bind when the request hits the server.
You have a two options to fix it:
Create the html by hand, setting the correct (expected) name; or:
In the iteration use an index so that the EditorFor generates the input with the expected name:
#{
var index = 0;
}
#foreach (var item in Model.FeatureList)
{
#Html.HiddenFor(model => model.FeatureList[index].FeatureId)
<div class="editor-label">
#Html.Label("Feature Name")
</div>
<div class="editor-field">
#Html.DisplayFor(model => model.FeatureList[index].FeatureName)
</div>
<div class="editor-label">
#Html.Label("Type")
</div>
<div class="editor-field">
#Html.DisplayFor(model => model.FeatureList[index].Type)
</div>
<div class="editor-label">
#Html.Label("Default Value")
</div>
<div class="editor-field">
#Html.DisplayFor(model => model.FeatureList[index].DefaultValue)
</div>
<div class="editor-label">
#Html.Label("Value")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FeatureList[index].Value)
</div>
index++;
}
I have tested and it just work worked fine. Have a nice weekend! Regards.

ViewModel List object return Null on HTTPPost

I am posting a form back to the server, the values are always null.
Model:
public class RDetailsViewModel
{
public RDetailsMaster RDetailsMaster { get; set; }
public ETransaction ETransaction { get; set; }
}
public class RDetailsMaster
{
[Required]
public List<QE_DROPDOWN_MST> Master_EQ { get; set; }
[Required]
public List<QE_DROPDOWN_MST> Master_BASIS { get; set; }
[Required]
public List<QE_DROPDOWN_MST> Master_TE { get; set; }
[Required]
public List<QE_DROPDOWN_MST> Master_ALOP { get; set; }
[Required]
public List<QE_DROPDOWN_MST> Master_RISK { get; set; }
[Required]
public List<QE_DROPDOWN_MST> Master_EXCESS { get; set; }
[Required]
public List<QE_DROPDOWN_MST> Master_CType { get; set; }
}
Controller:
[HttpPost]
public ActionResult RDetails(RDetailsViewModel ObjR)
{
return view();
}
My View :
#model QMS_ERater.ViewModels.RDetailsViewModel
#{
ViewBag.Title = "RDetails";
}
<script src="~/Scripts/EAR/RDetails.js"></script>
#using (Html.BeginForm("RDetails", "RDetails", FormMethod.Post))
{
<h2>RDetails</h2>
<div class="well well-sm">
<div id="divDetail101" runat="server">
<div class="row">
<div class="col-sm-4">
<span style="vertical-align: top; color: Red">*</span> EQ :
</div>
<div class="col-sm-3">
#Html.DropDownListFor(m => m.ETransation.EQ, new SelectList(Model.RDetailsMaster.Master_EQ, "VALUE", "DESCRIPTION"), "--Select--", new { style = "width: 100%;" })
</div>
<div class="col-sm-2">
<span style="vertical-align: top; color: Red">*</span> On First Loss Basis :
</div>
<div class="col-sm-3">
#Html.DropDownListFor(m => m.ETransation.BASIS, new SelectList(Model.RDetailsMaster.Master_BASIS, "VALUE", "DESCRIPTION"), "--Select--", new { style = "width: 100%;" })
</div>
<div class="col-sm-4">
<span style="vertical-align: top; color: Red">*</span> Terrorism :
</div>
<div class="col-sm-3">
#Html.DropDownListFor(m => m.ETransation.IS_TE, new SelectList(Model.RDetailsMaster.Master_TE, "VALUE", "DESCRIPTION"), "--Select--", new { style = "width: 100%;" })
</div>
<div class="col-sm-2">
<span style="vertical-align: top; color: Red">*</span> ALOP :
</div>
<div class="col-sm-3">
#Html.DropDownListFor(m => m.ETransation.IS_ALOP, new SelectList(Model.RDetailsMaster.Master_ALOP, "VALUE", "DESCRIPTION"), "--Select--", new { style = "width: 100%;" })
</div>
<div class="col-sm-4">
<span style="vertical-align: top; color: Red">*</span> Wet Risk :
</div>
<div class="col-sm-3">
#Html.DropDownListFor(m => m.ETransation.IS_RISK, new SelectList(Model.RDetailsMaster.Master_RISK, "VALUE", "DESCRIPTION"), "--Select--", new { style = "width: 100%;" })
</div>
</div>
</div>
<input type="submit" value="Submit" />
</div>
}
When I am trying call post method objR return NULL value for only List objects.
Any help would be greatly appreciated.
Thanks in advance!