I'm working with MVC 4 EF Code First and I have an object with an Edit View and it works properly. Then I created a very similar Create View, only when I click on the submit button I don't hit any breakpoints in the Controller. How do I tell what's wrong here? Is there somewhere I can set a breakpoint in either JavaScript or code-behind?
Model
public class ThirdParty : BaseModel
{
public Int32 Id { get; set; }
[MaxLength(2)]
private String CountryCode { get; set; }
[MaxLength(6)]
private Int32 SequenceNumber { get; set; }
public String UIN
{
get
{
if (CountryCode != null && SequenceNumber > 0)
return CountryCode.ToString() + "-" + SequenceNumber.ToString();
else
return null;
}
set
{
CountryCode = value.ToString().Substring(0, 2);
SequenceNumber = Int32.Parse(value.ToString().Substring(3, value.Length-3));
}
}
[MaxLength(250)]
[Required(AllowEmptyStrings = false, ErrorMessage = "{0} is required.")]
public String Name { get; set; }
public virtual ICollection<RelationshipType> RelationshipTypes { get; set; }
// Address
public Int32 AddressId { get; set; }
[ForeignKey("AddressId")]
public virtual Address Address { get; set; }
public bool IsImported { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<Attachment> Attachments { get; set; }
// constructor
public ThirdParty()
{
RelationshipTypes = new HashSet<RelationshipType>();
Attachments = new HashSet<Attachment>();
}
}
Controller Methods
public ActionResult Edit(int id)
{
ThirdPartyContext context = new ThirdPartyContext();
ThirdParty model = context.ThirdParties.Find(id);
ViewBag.Countries = context.Countries.ToList<Country>();
return View(model);
}
[HttpPost]
public ActionResult Edit(string button, ThirdParty model, int id)
{
if (button == "cancel")
return RedirectToAction("Index");
if (ModelState.IsValid)
{
ThirdPartyContext context = new ThirdPartyContext();
model.Address.Country = context.Countries.Find(model.Address.CountryId);
context.Entry(model.Address.Country).State = EntityState.Modified;
context.Entry(model.Address).State = EntityState.Modified;
context.Entry(model).State = EntityState.Modified;
context.SaveChanges();
Success("Third Party record updated!");
return RedirectToAction("Index");
}
else
{
ThirdPartyContext context = new ThirdPartyContext();
model.Address = context.Addresses.Find(model.AddressId);
return View("Edit", model);
}
}
public ActionResult Create()
{
ThirdPartyContext context = new ThirdPartyContext();
ViewBag.Countries = context.Countries.ToList<Country>();
return View();
}
[HttpPost]
public ActionResult Create(ThirdParty model)
{
if (ModelState.IsValid)
{
ThirdPartyContext context = new ThirdPartyContext();
List<ThirdParty> models = context.ThirdParties.ToList<ThirdParty>();
model.Id = models.Count() == 0 ? 1 : models.Select(x => x.Id).Max() + 1;
context.ThirdParties.Add(model);
context.SaveChanges();
Success("Your information was saved!");
return RedirectToAction("Index");
}
Error("There were some errors in your form.");
return View(model);
}
[HttpPost]
public ActionResult Create(string button, ThirdParty model)
{
if (button == "cancel")
return RedirectToAction("Index");
if (ModelState.IsValid)
{
ThirdPartyContext context = new ThirdPartyContext();
List<ThirdParty> models = context.ThirdParties.ToList<ThirdParty>();
model.Id = models.Count() == 0 ? 1 : models.Select(x => x.Id).Max() + 1;
context.ThirdParties.Add(model);
context.SaveChanges();
Success("Your information was saved!");
return RedirectToAction("Index");
}
Error("There were some errors in your form.");
return View(model);
}
Edit View
#model Models.ThirdParty
#{
ViewBag.Title = "Edit";
Layout = "~/Views/shared/ContentLayout.cshtml";
}
<div class="row">
<div class="col-lg-12">
<div class="page-header">
<h2>Third Party</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
#using (Html.BeginForm("Edit", "ThirdParty", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="form-group">
#Html.HiddenFor(model => model.Id)
<div class="clearfix visible-xs"></div>
#Html.HiddenFor(model => model.Address.Id)
</div>
<div class="form-group">
#Html.EditorFor(model => model.UIN)
<div class="clearfix visible-xs"></div>
#Html.EditorFor(model => model.Name)
</div>
#Html.HiddenFor(model => model.AddressId)
#Html.Partial("_EditAddress", Model)
#Html.HiddenFor(model => model.CreatedBy)
#Html.HiddenFor(model => model.CreatedOn)
#Html.HiddenFor(model => model.ModifiedBy)
#Html.HiddenFor(model => model.ModifiedOn)
<p>
<button name="button" type="submit" class="btn btn-default" value="cancel">Cancel</button>
<button name="button" type="submit" class="btn btn-primary" value="submit">Submit</button>
</p>
}
</div>
</div>
** Create View **
#model Models.ThirdParty
#{
ViewBag.Title = "Create";
Layout = "~/Views/shared/ContentLayout.cshtml";
}
<div class="row">
<div class="col-lg-12">
<ul class="breadcrumb" style="margin-bottom: 5px;">
<li>Third Parties</li>
<li class="active">Create New Third Party</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="page-header">
<h2>Create Third Party</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-2"> </div>
<div class="col-lg-8">
#using (Html.BeginForm("Create", "ThirdParty", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.EditorFor(model => model.UIN)
#Html.EditorFor(model => model.Name)
#Html.HiddenFor(model => model.AddressId)
#Html.Partial("_EditAddress", Model)
#Html.HiddenFor(model => model.CreatedBy)
#Html.HiddenFor(model => model.CreatedOn)
#Html.HiddenFor(model => model.ModifiedBy)
#Html.HiddenFor(model => model.ModifiedOn)
<p>
<button name="button" type="submit" class="btn btn-default" value="cancel">Cancel</button>
<input name="button" type="submit" class="btn btn-primary" value="submit" title="Submit" />
<input type="submit" value="Create" />
</p>
}
</div>
<div class="col-lg-2"> </div>
</div>
Edit:
I may have left out a critical part. I have these 4 hidden fields on the ThirdParty and Address models that I am planning to set in the controller Create method (if I can ever get in there). Here's the Model:
public class BaseModel
{
[HiddenInput(DisplayValue = false)]
public Int32 CreatedBy { get; set; }
[HiddenInput(DisplayValue = false)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime CreatedOn { get; set; }
[HiddenInput(DisplayValue = false)]
public Int32 ModifiedBy { get; set; }
[HiddenInput(DisplayValue = false)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime ModifiedOn { get; set; }
}
I was thinking that maybe my view is invalid and that's why it's not sending it to the controller. Here's how these look in the page markup:
<input data-val="true" data-val-number="The field CreatedBy must be a number." data-val-required="The CreatedBy field is required." id="Address_CreatedBy" name="Address.CreatedBy" type="hidden" value="" />
<input data-val="true" data-val-date="The field CreatedOn must be a date." data-val-required="The CreatedOn field is required." id="Address_CreatedOn" name="Address.CreatedOn" type="hidden" value="" />
<input data-val="true" data-val-number="The field ModifiedBy must be a number." data-val-required="The ModifiedBy field is required." id="Address_ModifiedBy" name="Address.ModifiedBy" type="hidden" value="" />
<input data-val="true" data-val-date="The field ModifiedOn must be a date." data-val-required="The ModifiedOn field is required." id="Address_ModifiedOn" name="Address.ModifiedOn" type="hidden" value="" />
<div class="form-group">
<input data-val="true" data-val-number="The field CreatedBy must be a number." data-val-required="The CreatedBy field is required." id="CreatedBy" name="CreatedBy" type="hidden" value="" />
<input data-val="true" data-val-date="The field CreatedOn must be a date." data-val-required="The CreatedOn field is required." id="CreatedOn" name="CreatedOn" type="hidden" value="" />
<input data-val="true" data-val-number="The field ModifiedBy must be a number." data-val-required="The ModifiedBy field is required." id="ModifiedBy" name="ModifiedBy" type="hidden" value="" />
<input data-val="true" data-val-date="The field ModifiedOn must be a date." data-val-required="The ModifiedOn field is required." id="ModifiedOn" name="ModifiedOn" type="hidden" value="" />
</div>
If your action gets called, setting a breakpoint at the beginning of your action and attaching to the process should do the trick.
Have you made sure that a POST request is sent from the browser when you click submit on your Create page ?
I haven't tried to run your code but note that you have defined two Create actions with the same name to process the POST verb.
This is likely to be ambiguous for the ASP.NET MVC as it cannot figure out what action to call.
Also, you are defining a ReturnUrl route value in the following line:
#using (Html.BeginForm("Create", "ThirdParty", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal" }))
This doesn't seem to be used in your action handling the POST.
Why do you have 2 submit buttons with the values "submit" and "create" ?
You can remove the Create action that takes the extra button parameter and replace the markup:
<button name="button" type="submit" class="btn btn-default" value="cancel">Cancel</button>
<input name="button" type="submit" class="btn btn-primary" value="submit" title="Submit" />
<input type="submit" value="Create" />
with something like:
<a class="btn btn-default" href="#Url.Action("Index", "ThirdParty")">Cancel</a>
<input name="button" type="submit" class="btn btn-primary" value="Create" title="Create" />
I invite you to read more documentation on how ASP.NET MVC Routing works.
Related
I have a method that I only use in one property where I upload photos so I only use the Photo property
I don't want to put the object as a parameter but a string that will be a replacement for the object and overwrite the Photo or in another way when using a Dto that fails to do gets null.
It's a function that works for me but I use the whole object as a parameter when I only use the PHOTO URL:
public async Task<string> UploadPhotos(IFormFile file, Product product)
{
string wwwPath = _environment.WebRootPath;
var path = Path.Combine(wwwPath, "images", file.FileName);
if (file.Length > 0)
{
using var stream = new FileStream(path, FileMode.Create);
await file.CopyToAsync(stream);
}
return product.PhotoUrl = file.FileName;
}
What I tried to do:
public async Task<string> UploadPhotos(IFormFile file, string photoUrl)
{
Product product = new()
{
PhotoUrl = photoUrl
};
string wwwPath = _environment.WebRootPath;
var path = Path.Combine(wwwPath, "images", file.FileName);
if (file.Length > 0)
{
using var stream = new FileStream(path, FileMode.Create);
await file.CopyToAsync(stream);
}
return product.PhotoUrl = file.FileName;
}
It doesn't work for me when I try to upload it doesn't show me the picture
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddProduct([FromForm] ProductViewModel model)
{
ModelState.Clear();
await _photoService.UploadPhotos(model.Photo,model.PhotoUrl);
if (ModelState.IsValid)
{
await _productRepository.AddProduct(model.Product!);
return RedirectToAction(nameof(Index));
}
return View();
}
ViewModel:
public class ProductViewModel
{
public Product Product { get; set; } = null!;
public string PhotoUrl { get; set; } = string.Empty;
public IFormFile Photo { get; set; } = null!;
}
View:
#model Solid_Project.Models.ProductViewModel
#{
ViewBag.Title = "AddProduct";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<article>
<section>
<form asp-action="AddProduct" enctype="multipart/form-data" method="post">
<div asp-validation-summary="ModelOnly"></div>
<div class="form-group">
<label asp-for="#Model.Product!.Name"></label>
<input asp-for="#Model.Product!.Name" class="form-control" placeholder="Enter Name" style="width:30%">
<span asp-validation-for="#Model.Product!.Name" class="validation"></span>
</div>
<br />
<div class="form-group">
<label asp-for="#Model.Product!.Description"></label>
<input asp-for="#Model.Product!.Description" class="form-control" placeholder="Enter Description" style="width:30%">
<span asp-validation-for="#Model.Product!.Description" class="validation"></span>
</div>
<br />
<div class="form-group">
<label asp-for="#Model.Product!.CategoryId"></label>
<div>
<select asp-for="#Model.Product!.CategoryId" asp-items="ViewBag.Category" style="width:30%" class="dropdown-toggle dropdown-toggle-design"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></select>
</div>
<span asp-validation-for="#Model.Product!.CategoryId" class="validation"></span>
</div>
<br />
<div class="form-group">
<label asp-for="#Model.Photo"></label>
<input type="file" asp-for="#Model.Photo" accept="image/*" class="form-control" style="width:30%" />
<span asp-validation-for="#Model.Photo" class="validation"></span>
</div>
<br />
<input type="submit" value="Create" class="btn btn-primary" />
</form>
</section>
</article>
#section Scripts {
#{
await Html.RenderPartialAsync("_ValidationScriptsPartial");
}
}
I have two classes "Customer" and "Deals" the customer has a foreign key relationship to the deal. The user should choose from the dropdown list the customer that makes the deal. So I create a ViewModel class that contains a SelectListItem of customers and a deal and update the creat in the deal controller, the error appears when creating the deals:
System.NullReferenceException HResult=0x80004003 Message=Object reference not set to an instance of an object.
-ViewModel:
public class CreateDealVM
{
public Deals deal { get; set; }
public IEnumerable<SelectListItem> selectedCustomer { get; set; }
public int selectedCustomerId { get; set; }
}
}
The DealController methods
public IActionResult Create()
{
Deals deal = new Deals();
List<Customer> customerList = _context.Customers.ToList();
CreateDealVM vm = new CreateDealVM();
vm.selectedCustomer = new SelectList(customerList, "customerId", "customerName");
vm.deal = deal;
return View(vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateDealVM vm)
{
if (ModelState.IsValid)
{
try
{
vm.deal.customer =_context.Customers.Find(vm.selectedCustomerId);
_context.Deals.Add(vm.deal);
_context.SaveChanges();
return RedirectToAction("Index");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return View(vm);
}
return View();
}
Deal Model class:
namespace MyShop.Models
{
[Table("Deals")]
public class Deals
{
[Key]
[Display(Name = "ID")]
public int dealId { get; set; }
[ForeignKey("Customer")]
[Display(Name = "Customer")]
public Customer customer { get; set; }
[Display(Name = "CustomerName")]
public string? parentCustomerName { get; set; }
[Display(Name = "product")]
public DealTypeEnum product { get; set; }
[Display(Name = "Date")]
public DateTime saleDate { get; set; }
[Display(Name = "Quantity")]
public float quantity { get; set; }
[Display(Name = "Price")]
public float price { get; set; }
}
The view.cshtml page :
#model MyShop.ViewModels.CreateDealVM
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Deals</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
#Html.LabelFor(model => model.selectedCustomer, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.selectedCustomerId, Model.selectedCustomer,"--Select--" )
</div>
</div>
<div class="form-group">
<label asp-for="deal.product" class="control-label"></label>
<select asp-for="deal.product" class="form-control"></select>
<span asp-validation-for="deal.product" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="deal.saleDate" class="control-label"></label>
<input asp-for="deal.saleDate" class="form-control" />
<span asp-validation-for="deal.saleDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="deal.quantity" class="control-label"></label>
<input asp-for="deal.quantity" class="form-control" />
<span asp-validation-for="deal.quantity" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="deal.price" class="control-label"></label>
<input asp-for="deal.price" class="form-control" />
<span asp-validation-for="deal.price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
I tried this link ASP.NET MVC DropdownlistFor Object reference not set to an instance of an object? but it did not work.
I suppose you have this problem not when you render the Create.cshtml view the first time, but after you press Create button and the ModelState.IsValid in the public ActionResult Create(CreateDealVM vm) is false.
After that you just render the Create.cshtml view by calling
return View();
This is why the Model is null when you trying to render the Create.cshtml view the second time.
You should use debugger to check this and if this is exactly what's happening replace return View(); line by
return View(vm);
In additional analyze your code in the view, to find out why the data model become not valid when passed from view to controller.
First thing first i want to apology if this topic has been mentioned before, but i looked for 2 days and never find about my problem.
So, I have a IFormFile script, which is does not throw any error (at least a syntax error) but when i am in the Upload Page, i complete my fields (Name,Description and File) and press Upload button, my OnPost code does not Fire at all and my page just referesh.
This is my Razor Page CREATE.CSHTML
#page
#model Appuntamenti.Models.ViewModel.DocumentCreateViewModel
#{
ViewData["Title"] = "Create";
Layout = "~/Pages/Shared/_Layout.cshtml";
}
<div>
<h4>Upload Single file</h4>
</div>
<form method="post" enctype="multipart/form-data" runat="server" asp-action="OnPost" class="mt-3">
<div class="form-group row">
<label asp-for="Name" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Name" class="form-control" placeholder="Name..." />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="Description" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="Description" class="form-control" placeholder="Description..." />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="Document" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<div class="custom-file">
<input asp-for="Document" class="form-control custom-file-input" />
<label class="custom-file-label">Choose File..</label>
</div>
</div>
</div>
<button type="submit" class="btn btn-success form-control"></button>
#section Scripts {
<script>
$(document).ready(function ()
{
$('.custom-file-input').on("change", function () {
var fileName = $(this).val().split("\\").pop();
$(this).next('.custom-file-label').html(fileName);
});
});
</script>
}
</form>
And This is my CREATE.CSHTML.CS page
namespace Appuntamenti.Pages.Documents
{
public class CreateModel : PageModel
{
private readonly ApplicationDbContext _db;
private readonly IHostingEnvironment _hostingEnvironment;
public CreateModel(ApplicationDbContext db, IHostingEnvironment hostingEnvironment)
{
_db = db;
_hostingEnvironment = hostingEnvironment;
}
[HttpPost]
public async Task<IActionResult> OnPostAsync (DocumentCreateViewModel model)
{
if (!ModelState.IsValid)
{
return NotFound();
}
string uniqueFileName = null;
if(model.Document != null)
{
string uploadsFolder = Path.Combine(_hostingEnvironment.WebRootPath, "Documents");
uniqueFileName = Guid.NewGuid().ToString() + "_" + model.Document.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
await model.Document.CopyToAsync(new FileStream(filePath, FileMode.Create));
}
DocumentModel newDocument = new DocumentModel
{
Id = model.Id,
Name = model.Name,
Description = model.Description,
DocumentPath = uniqueFileName
};
_db.Add(newDocument);
_db.SaveChanges();
return RedirectToPage("./Index");
}
}
}
And Those are my 2 Models for the IFormFile
public class DocumentModel
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string DocumentPath { get; set; }
}
public class DocumentCreateViewModel
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public IFormFile Document { get; set; }
}
BAsically i tried to put a Breakpoint on the Post Method but it does not fire at all,
I tried to run the Website and inspect the elements,header and network and everything is ok.
After some browsing i read that the Onpost method with the IFormFile rely on the TokenValidation, i tried to ignore the validation and see if something change but nothing. I really dont know what i am doing wrong.
I hope i made my point and problem clear and please if you need more info just let me know
You mixed up Asp.Net Core MVC and Razor Page.
Follow steps below:
CreateModel
public class CreateModel : PageModel
{
[BindProperty]
public DocumentCreateViewModel DocumentCreateViewModel { get; set; }
//[HttpPost]
public async Task<IActionResult> OnPostAsync()
{
return RedirectToPage("./Index");
}
View
#page
#model CreateModel
#{
ViewData["Title"] = "Create";
Layout = "~/Pages/Shared/_Layout.cshtml";
}
<div>
<h4>Upload Single file</h4>
</div>
<form method="post" enctype="multipart/form-data">
<div class="form-group row">
<label asp-for="DocumentCreateViewModel.Name" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="DocumentCreateViewModel.Name" class="form-control" placeholder="Name..." />
<span asp-validation-for="DocumentCreateViewModel.Name" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="DocumentCreateViewModel.Description" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<input asp-for="DocumentCreateViewModel.Description" class="form-control" placeholder="Description..." />
<span asp-validation-for="DocumentCreateViewModel.Description" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label asp-for="DocumentCreateViewModel.Document" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<div class="custom-file">
<input asp-for="DocumentCreateViewModel.Document" type="file" class="form-control custom-file-input" />
<label class="custom-file-label">Choose File..</label>
</div>
</div>
</div>
<button type="submit" class="btn btn-success form-control"></button>
#*<input type="submit" value="Submit" />*#
</form>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
$(document).ready(function () {
$('.custom-file-input').on("change", function () {
var fileName = $(this).val().split("\\").pop();
$(this).next('.custom-file-label').html(fileName);
});
});
</script>
}
For more information about Razor page, refer Introduction to Razor Pages in ASP.NET Core
I am trying to add validations on my View. But I am unable to access the property inside #Html.ValidationMessageFor(?)
My View
#model IEnumerable<Entity.Employee>
<div class="jumbotron">
#using (Html.BeginForm("Create", "Employee", FormMethod.Post))
{
<label>Name</label>
<input id="txtName" type="text" name="EmployeeName" class="btn btn-default" />
#Html.ValidationMessageFor(model => model. //not able to get the Name property
<input type="submit" value="Save" class="btn btn-primary" />
}
</div>
Employee Class
[Required(ErrorMessage="Please enter name")]
public string Name { get; set; }
Controller
[HttpPost]
public ActionResult Create(Employee employee, string EmployeeName)
{
if (ModelState.IsValid)
{
employee.Name = EmployeeName;
repository.SaveRole(role);
return RedirectToAction("Index");
}
else
{
return View(employee);
}
}
I am not sure what have I missed or is it because the View is Strongly couple to IEnumerable<Type>
Your view has defined model of type IEnumerable<Entity.Employee>. This stands for multiple employees. You should change your model declaration to
#model Entity.Employee
I have the following ViewModel
public class EditPatientViewModel
{
public Domain.Entities.Patient patient;
public IEnumerable<Espece> Especes;
public IEnumerable<Client> Clients;
}
the following controller
public ViewResult Edit(int Id_pat)
{
var ViewModel = new EditPatientViewModel();
ViewModel.patient = patientRepo.GetPatientById(Id_pat);
ViewModel.Especes = especeRepo.Especes;
return View(ViewModel);
}
[HttpPost]
public ActionResult Edit(EditPatientViewModel editPatientViewModel)
{
if (ModelState.IsValid)
{
patientRepo.Save(editPatientViewModel.patient);
TempData["message"] = "Sauvé";
return RedirectToAction("Index");
}
else
{
return View(editPatientViewModel);
}
}
and the following view
#model Veto.Models.ViewModels.EditPatientViewModel
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Edit Patient</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
<div class="col-md-10">
#Html.HiddenFor(m => m.patient.Id_pat)
</div>
</div>
<div class="form-group">
<div class="col-md-10">
#Html.EditorFor(m => m.patient.Nom_pat)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Every time I submit the form the ViewModel posted is not null but attributes are.. I would like to retrieve the attributes to make an update.
Why?
Tx,
Two same problem in one hour :)
Change your ViewModel to this:
public class EditPatientViewModel
{
public Domain.Entities.Patient patient { get; set; }
public IEnumerable<Espece> Especes { get; set; }
public IEnumerable<Client> Clients { get; set; }
}
In complex types, mvc model binder search for properties not for member variables.