ASP .Net MVC Form not calling controller on submit - c#

I am having trouble getting my view to call the post method in my MVC Controller. When I click on the submit button, it does not call the Create method. I add a breakpoint, but it never gets to the code. I am assuming some error, but not sure how to see the error message.
Here is the View:
#model PersonViewModel
#{
ViewBag.Title = "Register";
}
#using (Html.BeginForm(PeopleControllerAction.Create, ControllerName.People, FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal row">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
</div>
<div class="row panel radius">
<div class="medium-2 columns">
<h3>Contact Information</h3>
</div>
<div class="medium-10 columns">
<div class="row">
<div class="medium-6 columns">
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
</div>
</div>
// more fields removed for brevity
<div class="row">
<div class="form-group">
<div>
<input type="submit" value="Submit" class="button" />
</div>
</div>
</div>
}
Here is the controller:
public class PeopleController : Controller
{
private IPersonService context { get; set; }
public PeopleController(IPersonService context)
{
this.context = context;
}
// POST: People/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "FirstName,LastName,Age,Email,Phone,City,State,HopeToReach,Story,Goal,Image")] PersonViewModel person)
{
if (ModelState.IsValid)
{
try
{
person.ImagePath = ImageUploader.UploadImage(person.Image);
}
catch (ArgumentException e)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, e.Message);
}
var id = await context.AddAsync(person);
return RedirectToAction(PeopleControllerAction.Confirmation);
}
return View(person);
}
}

This was resolved. The action in question did not have a route. I am using attribute routing.

Related

PopUp not sending data in database in ASP.NET MVC 5 and Entity Framework

The popup code works just fine but after I add the credentials and click on the submit button to create the record nothing happens. I'm new to ASP.NET MVC 5 and Entity Framework 6. Any guidance will be most appreciated.
#model IEnumerable <LogInTest1.Models.Credentials>
#{var createModel = new LogInTest1.Models.Credentials();} #* I think I didn't do this part right *#
#{
ViewBag.Title = "Index";
}
Here is the button code:
<button class="btn btn-default" onclick="AddData()">Click to Create »</button>
<script>
function AddData() {
$("#MyModal").modal();
}
</script>
Here is the popup code:
<div class="modal fade" id="MyModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4>Add Data</h4>
</div>
<div class="modal-body">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => createModel.userName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => createModel.userName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => createModel.userName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => createModel.password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => createModel.password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => createModel.password, "", new { #class = "text-danger" })
</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>
</div>
</div>
</div>
Data get easily added in the create view:
<p>
#Html.ActionLink("Create New", "Create")
</p>
Table code:
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.userName)
</th>
<th>
#Html.DisplayNameFor(model => model.password)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.userName)
</td>
<td>
#Html.DisplayFor(modelItem => item.password)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.empId }) |
#Html.ActionLink("Details", "Details", new { id = item.empId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.empId })
</td>
</tr>
}
</table>
Controller code:
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using LogInTest1.Models;
namespace LogInTest1.Controllers
{
public class CredentialsController : Controller
{
private CredentialsContext db = new CredentialsContext();
// GET: Credentials
public ActionResult Index()
{
return View(db.Cr.ToList());
}
// GET: Credentials/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Credentials credentials = db.Cr.Find(id);
if (credentials == null)
{
return HttpNotFound();
}
return View(credentials);
}
// GET: Credentials/Create
public ActionResult Create()
{
return View();
}
// POST: Credentials/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "empId,userName,password")] Credentials credentials)
{
if (ModelState.IsValid)
{
db.Cr.Add(credentials);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(credentials);
}
// GET: Credentials/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Credentials credentials = db.Cr.Find(id);
if (credentials == null)
{
return HttpNotFound();
}
return View(credentials);
}
// POST: Credentials/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "empId,userName,password")] Credentials credentials)
{
if (ModelState.IsValid)
{
db.Entry(credentials).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(credentials);
}
// GET: Credentials/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Credentials credentials = db.Cr.Find(id);
if (credentials == null)
{
return HttpNotFound();
}
return View(credentials);
}
// POST: Credentials/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Credentials credentials = db.Cr.Find(id);
db.Cr.Remove(credentials);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
paste this code into your index page <div class="modal fade" id="MyModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4>Add Data</h4>
</div>
<div class="modal-body">
#{ Html.RenderPartial("~/Views/Credentials/Create.cshtml", new Credentials());}
</div>
</div>
</div>
</div>
<button class="btn btn-default" onclick="AddData()">Click to Create »</button>
<script>
function AddData() {
$("#MyModal").modal();
}
</script>
And your Create page should like this
#model MvcWithDI.Models.Credentials
#using (Html.BeginForm("Create","Credentials",FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Credentials</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.userName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.userName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.userName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.password, "", new { #class = "text-danger" })
</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>
}

Varying amount of fields in Razor page form, returns null properties in view model

I've come up with problem, when trying to fill data to my model. I have an "Resource" entity, which can have no-to-many "attributes". I have templates set up, which holds names for those attributes. When Resource is created, user chooses on of templates, then Attributes are created(empty) and program generates form for those attributes.
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(Model => Model.Resource)
#for (int i = 0; i < Model.Attributes.Count(); i++)
{
<div class="form-group">
#*Html.LabelFor(d => d.Attributes.ToArray()[i].Name, htmlAttributes: new { #class = "control-label col-md-2" })*#
<h4>#Html.Raw(Model.Attributes.ToList()[i].Name)</h4>
<div class="col-md-10">
#Html.TextBoxFor(Model => Model.Attributes.ToList()[i].Value, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(Model => Model.Attributes.ToList()[i].Value, "", new { #class = "text-danger" })
</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>
}
This form uses this View model:
public class ResourceAttributesViewModel
{
public virtual Resource Resource { get; set; }
public virtual ICollection<_Attribute> Attributes { get; set; }
}
problem is that when i hit "submit" button, it gives me view model with null Resource and Attributes properties
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Fill(ResourceAttributesViewModel AttributeSet)
{
if(ModelState.IsValid)
{
foreach (var attr in AttributeSet.Attributes)
{
db.Entry(attr).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("Index");
}
return View(AttributeSet);
}
if it helps, there is POST string sent by browser
__RequestVerificationToken=XoVM9h_3njX5x2m35b_vKKHY3m5UDaYm9_2ZMfNkglouqHJCSw2NO56Tv2Sb3kXy8qC8XBLXawoQv0ft0xc-LxYmQGfi4EAqroq2b63Wb9Q1&Resource=System.Data.Entity.DynamicProxies.Resource_7639327FA0332BEBC7FB6836F70C3D62C3D744D76F2C3F8DDFCE679AA8CA31DC&%5B0%5D.Value=100&%5B1%5D.Value=200

View model parameter is null in HttpPost action method

I am redirecting my viewModel from the HttpPost of View1 to the HttpGet of View2.
This works without problems.
There the user has to accept the terms and agreemens.
This should get changed in the viewModel to true (before it is false).
And then redirect to the HttpPost of view2.
There something goes wrong.
The HttpPost ActionResult of View2 receives the viewModel with all Parameters as NULL (before they were filled)
How can I fix this?
Here is my HttpGet ActionResult for View2:
public ActionResult Verify(QuestionViewModel viewModel)
{
//Anrede in Viewbag
if (viewModelVeri.Per_Salutation == 2)
{
ViewBag.Per_Salutation = "Frau";
}
else
{
ViewBag.Per_Salutation = "Herr";
}
int? per_region_id = viewModelVeri.Per_Region;
int per_region_id_nullable = Convert.ToInt32(per_region_id);
Region region = _repository.GetRegionById(per_region_id_nullable);
QuestionViewModel viewModel2 = new QuestionViewModel()
{
Reg_Name = region.Reg_Name
};
//Regionsname in Viewbag
ViewBag.Reg_Name = viewModel2.Reg_Name;
return View(viewModel);
}
And here's my HttpPost ActionResult for View2:
[HttpPost]
public ActionResult Verify(QuestionViewModel viewModel, string tbButton)
{
//here the ViewModel-Parameters are already NULL
My View:
<div class="panel-body">
#using (Html.BeginForm("Verify", "QuestionForm", FormMethod.Post, new { id = "verifyform" }))
{
#Html.AntiForgeryToken()
<div class="ctrl-row">
<div class="form-group">
<div class="container-fluid">
#Html.LabelFor(model => model.Per_Salutation, new { #class = "control-label col-sm-1" })
<div class="col-sm-3">
#ViewBag.Per_Salutation
</div>
</div>
</div>
</div>
<div class="ctrl-row">
<div class="form-group">
<div class="container-fluid">
#Html.LabelFor(model => model.Per_Name_Last, new { #class = "control-label col-sm-1" })
<div class="col-sm-3">
#Html.DisplayFor(model => model.Per_Name_Last, new { #class = "control-label col-sm-1 non-zero-num" })
</div>
#Html.LabelFor(model => model.Per_Name_First, new { #class = "control-label col-sm-1" })
<div class="col-sm-3">
#Html.DisplayFor(model => model.Per_Name_First, new { #class = "control-label col-sm-1 non-zero-num" })
</div>
</div>
</div>
</div
<div class="ctrl-row">
<div class="form-group">
<div class="container-fluid">
#Html.LabelFor(model => model.Per_EMail, new { #class = "control-label col-sm-1" })
<div class="col-sm-8">
#Html.DisplayFor(model => model.Per_EMail, new { #class = "control-label col-sm-1 non-zero-num" })
</div>
</div>
</div>
</div>
<div class="checkbox">
<input type="checkbox" id="NutzungsbedingungenAngenommen " />
<label for="NutzungsbedingungenAngenommen ">
Ich erkläre mich mit den Nutzungsbedingungen einverstanden.
</label>
</div>
<button class="btn btn-default" type="submit" name="tbButton" value="questsend">Senden</button>
}
<script>
$(document).ready(function () {
$(".non-zero-num").val($(this).val() == 0 ? ' ' : $(this).val());
})
$('#verifyform').on('click', '[value="questsend"]', function () {
if ($('#agree').is(':checked')) {
return true;
}
else {
return false;
}
});
</script>
EDIT
Here my QuestionViewModel
public class QuestionViewModel
{
//Other Properties
[Required(ErrorMessage = "Bitte die Nutzungsbedingungen annehmen!")]
public bool NutzungsbedingungenAngenommen { get; set; }
}
My HttpPost Controller for View1:
[HttpPost]
public ActionResult DefaultForm(QuestionViewModel viewModel, string tbButton)
{
if (ModelState.IsValid)
{
try
{
if (tbButton.Equals("questsend"))
{
return RedirectToAction("Verify", viewModel);
}
else if (tbButton.Equals("questupload"))
{
//write to DB
return View(viewModel);
}
else
{
dropdownPopulate(viewModel);
return View("DefaultForm", viewModel);
}
}
catch
{
dropdownPopulate(viewModel);
return View(viewModel);
}
}
else
{
dropdownPopulate(viewModel);
return View(viewModel);
}
}
The problem is you use Html.DisplayFor to display the property values of viewModel in View2, so the values won't be submitted to the HttpPost method, hence viewModel is null when HttpPost for View2 is executed. Only values in <input>, <textarea> and <select> tags will be submitted.
You can submit the values of viewModel to the HttpPost for View2 by adding Html.HiddenFor inside Html.BeginForm for all properties of viewModel. You should also use Html.CheckBoxFor(m => m.NutzungsbedingungenAngenommen) for the checkbox. Something like below should work
#using (Html.BeginForm("Verify", "QuestionForm", FormMethod.Post, new { id = "verifyform" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.Per_Salutation)
#Html.HiddenFor(m => m.Per_Name_First)
#Html.HiddenFor(m => m.Per_Name_Last)
.... // Html.HiddenFor for the rest of QuestionViewModel properties
....
.... // the rest of your code inside the form tag
.... // remove <input type="checkbox" id="NutzungsbedingungenAngenommen " />
#Html.CheckBoxFor(m => m.NutzungsbedingungenAngenommen)
<button class="btn btn-default" type="submit" name="tbButton" value="questsend">Senden</button>
}
Make sure you declare what model should be used by Razor.
#model QuestionViewModel
Make sure the name and id of your HTML inputs are in the format expected by the MVC modelbinder. I recommend using the provided HtmlHelpers instead of writing the input tags by hand.
#Html.CheckBoxFor(m => m.Agree)
Remove the string tbButton parameter from your POST action

MVC throwing HTTP 404 error

I am completely stuck and confused why it works with one View to Controller but not the other one.
The one that works:
public class HomeController : Controller
{
// GET: Home
IAuthenticationManager Authentication
{
get { return HttpContext.GetOwinContext().Authentication; }
}
public ActionResult Index()
{
return View();
}
[POST("login")]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel input)
{
if (ModelState.IsValid)
{
if (input.HasValidUsernameAndPassword())
{
var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name, input.Username),
},
DefaultAuthenticationTypes.ApplicationCookie,
ClaimTypes.Name, ClaimTypes.Role);
// if you want roles, just add as many as you want here (for loop maybe?)
if (input.isAdministrator)
{
identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));
}
else
{
identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
}
// tell OWIN the identity provider, optional
// identity.AddClaim(new Claim(IdentityProvider, "Simplest Auth"));
Authentication.SignIn(new AuthenticationProperties
{
IsPersistent = input.RememberMe
}, identity);
return RedirectToAction("password", "authentication");
}
}
return View("show", input);
}
[GET("logout")]
public ActionResult Logout()
{
Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
return RedirectToAction("login");
}
}
With this CSHTML code:
#model AgridyneAllIn1MVC.Models.Authentication.LoginModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Details</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Username, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Username)
#Html.ValidationMessageFor(model => model.Username)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.RememberMe, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.RememberMe)
#Html.ValidationMessageFor(model => model.RememberMe)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Login" class="btn btn-default" />
</div>
</div>
</div>
}
The CSHTML that doesn't work is:
#using Microsoft.AspNet.Identity
#model AgridyneAllIn1MVC.Models.Authentication.LoginModel
#if(User.Identity.IsAuthenticated)
{
using (Html.BeginForm("resetpassword", "authentication", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Reset your password.</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.Username, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Username, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Reset" />
</div>
</div>
}
}
The Controller that goes with it is:
public class AuthenticationController : Controller
{
[Authorize]
public ActionResult Password()
{
return View("ResetPassword");
}
[Authorize]
public ActionResult Register()
{
return View("Register");
}
[Authorize]
[POST("resetpassword")]
public ActionResult ResetPassword(LoginModel input)
{
if (ModelState.IsValid)
{
if (User.Identity.IsAuthenticated)
{
if(input.SuccessfullyUpdatedPassword())
{
return View("Password");
}
}
}
return View("Password");
}
[Authorize]
[POST("registernewuser")]
public ActionResult RegisterNewUser(LoginModel input)
{
if (ModelState.IsValid)
{
if (User.Identity.IsAuthenticated)
{
if (input.SuccessfullyUpdatedPassword())
{
return View();
}
}
}
return View();
}
}
Every time I try to get to either of those pages I get
The resource cannot be found. HTTP 404. Requested URL: /resetpassword.
Am I missing something that is required in the HTML.BeginForm() that would make it go to the correct ActionEvent to fire off my code and update the view? This is my first MVC that I am building from scratch and designing the views from scratch. Does MVCs have a problem with having multiple views to one controller? What gets me is that the MVC that works doesn't have anything filled in the HTML.BeginForm(), I tried it without having anything in HTML.BeginForm() and I get the same result. I tried with changing the [GET("resetpassword")] to [GET("")] and it doesn't work either. I have another view that is called register and it has the same problem with the AuthenticationController. So can someone please tell me what is wrong and explain why so I can fully understand how MVC wants things to be done so I get it right for the other 50 plus views that I still have to build yet.
Your Form use FormMethod.Post but there aren't exist POST resetpassword method in your Controller
Change the [GET("resetpassword")] to POST because the form from cshtml file use the post method:
using (Html.BeginForm("resetpassword", "authentication", FormMethod.Post,....

MVC5 ViewModel Not Posting back to Controller

So, I have an issue with a controller/view/viewmodel. It's similar to this issue I think. Basically, I have a viewmodel that I send to a view from my controller. There are items that display and then some additional fields for the user to manipulate before the whole mess is sent back over to a controller post action. When I get the data back in my post, all of the viewmodel is empty.
So, without further ado, here's some code to look at:
ViewModel:
public class ASideReceivingViewModel
{
public PurchaseOrderLine poLine;
public ReceivingItem receivingItem;
public Dictionary<string, string> TankerOrRailcarOptions { get; set; }
public ASideReceivingViewModel()
{
TankerOrRailcarOptions = new Dictionary<string, string>();
TankerOrRailcarOptions.Add("R", "Railcar");
TankerOrRailcarOptions.Add("T", "Tanker");
}
}
Controller Actions:
public ActionResult Receive(string strOrdNo, short? shtLineNo)
{
//if there isn't a selected po line, then shoot them back to the first page
if (strOrdNo == null || !shtLineNo.HasValue) return RedirectToAction("Index");
PurchaseOrderService poService = new PurchaseOrderService();
ReceivingItemService s = new ReceivingItemService(p);
ASideReceivingViewModel vm = new ASideReceivingViewModel();
vm.poLine = poService.GetOpenPurchaseOrderLines().Where(po => po.Ord_no == strOrdNo &&
po.Line_no == shtLineNo).FirstOrDefault();
if (vm.poLine == null) return RedirectToAction("Index");
vm.receivingItem = s.CreateNewReceivingItem(vm.poLine);
return View(vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Receive(ASideReceivingViewModel mytestvm)
{
if (ModelState.IsValid && mytestvm.receivingItem != null)
{
ReceivingItemService s = new ReceivingItemService(p);
s.Update(mytestvm.receivingItem);
return RedirectToAction("Index");
}
return View(mytestvm);
}
View:
#model FSIApps.Presentation.Models.ASideReceivingViewModel
<div class="row">
#{Html.RenderPartial("POLineDetails", Model.poLine);}
</div>
#using (Html.BeginForm("Receive", "Receiving", FormMethod.Post))
{
#Html.HiddenFor(model => model.receivingItem.Id)
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="row">
#Html.AntiForgeryToken()
<div class="col-md-6">
<div class="form-group">
<label for="receivingItem_Batch_number">Batch Number</label>
#Html.TextBoxFor(model => model.receivingItem.Batch_number, new { #class = "form-control" })
<span class="help-block">*Also the Vendor Lot Number on the BOL</span>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="receivingItem_Qty_received">Qty Received</label>
#Html.TextBoxFor(model => model.receivingItem.Qty_received, new { #class = "form-control" })
<span class="help-block">*Qty shown on BOL</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="receivingItem_Carrier">Carrier</label>
#Html.TextBoxFor(model => model.receivingItem.Carrier, new { #class = "form-control" })
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="receivingItem_">Tanker or Railcar</label>
#Html.DropDownListFor(m => m.receivingItem.Tanker_or_railcar, new SelectList(Model.TankerOrRailcarOptions, "Key", "Value", Model.receivingItem.Tanker_or_railcar), new { #class = "form-control" })
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="receivingItem_Railcar_number">Railcar Number</label>
#Html.TextBoxFor(model => model.receivingItem.Railcar_number, new { #class = "form-control" })
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="receivingItem_Manifest_number">Manifest Number</label>
#Html.TextBoxFor(model => model.receivingItem.Manifest_number, new { #class = "form-control" })
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input type="submit" value="Save" class="btn btn-success" />
</div>
</div>
</div>
</div>
</div>
}
I don't necessarily care about the data I send to the partial view, but when I post back the regular form I get nothing set in the ViewModel. In the other post they talk about how that's an issue with naming the parameter sent back to the controller, but no combination of setting the value in my #Html.BeginForm() seems to do the trick.
Anyone have any advice for me here?
Edited:
To use the automatic model binding, you should use properties instead of fields in the view model. Hopefully this does the trick:
public class ASideReceivingViewModel
{
public PurchaseOrderLine poLine { get; set; };
public ReceivingItem receivingItem { get; set; };
...
}

Categories