ViewModel attributes always null when posted - asp.net-mvc-4

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.

Related

Adding collection of items in Many to Many Relationship in ASP.NET Core MVC Problem (Code first)

I have two Entities that have many To many relationship, Book and Tags asp Created automatically a table for the two entities, Using the code first approach
I am trying to add a collection of tags in the book creation, but the tag items are null also there is (select asp-for="Tags" ) but it shows me null in [httppost]create.
I tried to add it in through context as it catches the values of tags I add, but there is an error
cannot convert ......dbset<> to Models.tags
Code:
public class Book
{
public int BookID { get; set; }
[Required]
public string Name { get; set; } = null!;
//Navigation property
public virtual ICollection<Tags>? Tags { get; set; }
}
public class Tags
{
public int TagsID { get; set; }
public string TagName { get; set; } = null!;
//Navigation property
public virtual ICollection<Book>? Book { get; set; }
}
//DB Context
public class BLabContext: DbContext
{
public DbSet<Book> Book { get; set; }
public DbSet<Tags> Tags { get; set; }
}
// Book Controller
public class BooksController : Controller
{
private readonly BLabContext _context;
public BooksController(BLabContext context)
{
_context = context;
}
// Tags objects
// public ICollection<Tags> Tags { get; set; }
// GET: Books
public async Task<IActionResult> Index()
{
return View(await _context.Book.ToListAsync());
}
// GET: Books/Create
(on get )
public IActionResult Create()
{
///πŸ’€πŸ’€πŸ’€πŸ’€πŸ’€πŸ’€πŸ’€
var tags = _context.Tags.ToList();
ViewData["tags"] = tags;
//ViewBag.tags = tags;
return View();
}
// POST: Books/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("BookID,Name,Description,PublishedOn,Publisher,Price,ImageURL,1)πŸ’€TagsπŸ’€")] Book book)
{
if (ModelState.IsValid)
{
2)πŸ’€
var tags = _context.Tags;
_context.Add(book);
await _context.SaveChangesAsync();
2)πŸ’€(cannot convert ......dbset<> to Models.tags
_context.Book.FirstOrDefault(b => b.BookID == book.BookID).Tags.Add(tags);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(book);
}
The create view:
#using Book_Library.Models;
#model Book_Library.Models.Book
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Book</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<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">
<label asp-for="Tags" class="control-label"></label>
#*name="Tags"*#
<select asp-for="Tags" multiple>
#foreach (var tag in #ViewData["tags"] as IList<Tags>)
{
<option value="#tag.TagName">#tag.TagName </option>
}
</select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
I expect to add a collection of tags to the book on creation, and also view those tags on the details view
You can create a ViewModel to achieve it, Please refer to this demo:
ViewModel
public class CreateBookViewModel
{
[Required]
public string BookName { get; set; }
public List<int> TagId { get; set; }
}
Controller
public IActionResult Create()
{
var tags = _context.Tags.ToList();
List<SelectListItem> dropdown = new List<SelectListItem>();
foreach (var item in tags)
{
var listItem = new SelectListItem();
listItem.Text = item.TagName;
listItem.Value = item.TagsID.ToString();
dropdown.Add(listItem);
}
ViewBag.tags = dropdown;
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(CreateBookViewModel book)
{
if (ModelState.IsValid)
{
Book b = new Book();
b.Name = book.BookName;
if (book.TagId.Count>0)
{
foreach (var item in book.TagId)
{
var tag = _context.Tags.Where(x => x.TagsID == item).FirstOrDefault();
b.Tags.Add(tag);
}
}
_context.Book.Add(b);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(book);
}
View
#model CreateBookViewModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Book</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="BookName" class="control-label"></label>
<input asp-for="BookName" class="form-control" />
<span asp-validation-for="BookName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="#Model.TagId" class="control-label"></label>
<select asp-for="#Model.TagId" asp-items="#ViewBag.tags" multiple></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{
await Html.RenderPartialAsync("_ValidationScriptsPartial");
}
}
Now, You can add collection of Tags to Book successfully.
Note: You need to instantiate Tags in your Book class, Otherwise the above code will report a nullreferenceexception.
public class Book
{
//.........
//Navigation property
public virtual ICollection<Tags>? Tags { get; set; } = new List<Tags>();
}

Asp.net core 6 Html.DropDownListFor System.NullReferenceException

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.

Asp.net Core Upload File Does not Fire OnPost Code

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

Entity Framework inserting long value instead of actual string value to database for my ASP.NET core site

My Entity Framework passes a string like this to the database "1b2ef80d-038a-49d8-973b-fc783a53b6a3" instead of the text i placed into the input field, which was "text". How can i only Insert the exact value into the table?
The Database table i'm currently testing is just one column and is set to VARCHAR(400).
Context class:
modelBuilder.Entity<Contract>(entity =>
{
entity.HasKey(e => e.Contract1)
.HasName("Contract$PrimaryKey");
entity.Property<string>(e => e.Contract1)
.HasColumnName("Contract")
.HasColumnType("VARCHAR(400)")
.IsUnicode(false)
.HasMaxLength(400);
});
Model class:
[Key]
[Column(TypeName = "VARCHAR(400)")]
[StringLength(400)]
public string Contract1 { get; set; }
View page:
<form asp-action="Create">
<div class="form-horizontal">
<h4>Contract</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
#Html.LabelFor(model => model.Contract1, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.EditorFor(model => model.Contract1)
#Html.ValidationMessageFor(model => model.Contract1)
<span class="text-danger"></span>
</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>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
</body>
</html>
And Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Contract")] Contract Contract)
{
if (ModelState.IsValid)
{
_context.Add(Contract);
await _context.SaveChangesAsync();
return RedirectToAction("Create");
}
ViewData["Contract"] = new SelectList(_context.Contract, "Contract", "Contract", Contract.Contract1);
return View(Contract);
}
}
}
i had to add the class, instead of just the context.Add i had to make it context.class.Add:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(Contract Contract)
{
if (ModelState.IsValid)
{
_context.Contract.Add(Contract);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewData["Contract"] = new SelectList(_context.Contract, "Contract", "Contract", Contract.Contract1);
return View(Contract);
}
}
}

How do I tell what's happening when I postback my view?

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.