Validating MVC Form with Multiple Tab - asp.net-mvc

I have this form with couple tabs that I needed to validate. Here is the issue I am encountered. I wanted to direct the user back to the "Tab Page" where required fields were not entered. For an example, if the user didn't select any of the Financial Section of selection then the Financial Tab page will shows the error message.
Here is the View page
#using CalFresh.Models
#model CalFresh.Models.calfreshByWorkUnitID
#using (Html.BeginForm())
{
<form id="msform" class="form-inline" method="post">
<div id="TabsSetMain">
<table>
<tr>
<td>Some reviewer info</td>
</tr>
</table>
</div>
#*--------------------- Sub Tabs (Household/Financial/Medical)-----
<div id="TabsSet1">
<ul id="progressbar">
<li>Household</li>
<li>Financial</li>
<li>Medical</li>
</ul>
</div>
#*-------------------- Household Tab -----------------
<div id="tabs-household">
<table>
<tr>
<td>Was the SSN Verified?</td>
#{
List<SelectListItem> listItems = new List<SelectListItem>();
listItems.Add(new SelectListItem
{
Text = " -- Select One -- ",
Value="",
Selected = true
});
listItems.Add(new SelectListItem
{
Text = "Yes",
Value="Yes"
});
listItems.Add(new SelectListItem
{
Text = "No",
Value="No"
});
}
<td>
#Html.DropDownListFor(model=>model.tempHouseHoldSSNVerification, listItems, new {#class="form-control", value=Model.tempHouseHoldSSNVerification})
#Html.ValidationMessageFor(model=>model.tempHouseHoldSSNVerification, null, new {style="color:red"})
</td>
</tr>
</table>
</div>
#*-------------------- Financial Tab -----------------
<div id=tabs-financial">
<table>
<tr>
<td>
Was an error found for earned income calculation?
</td>
<td>
#Html.DropDownListFor(model=>model.tempFinancialEarnIncome, listItems, new {#class="form-control", value=Model.tempHouseHoldSSNVerification})
#Html.ValidationMessageFor(model=>model.tempFinancialEarnIncome, null, new {style="color:red"})
</td>
</tr>
</table>
</div>
</form>
}
<script>
$(function () {
$("#TabsSetMain").tabs();
});
</script>
<script>
$(function () {
$("#TabsSet1").tabs();
});
</script>
Here is the class page
using System;
using System.ComponentModel.DataAnnotations;
namespace CalFresh.Models
{
public class calfreshByWorkUnitID
{
[Required(ErrorMessage = "Please select Household SSN verification.")]
public string tempHouseHoldSSNVerification { get; set; }
[Required(ErrorMessage = "Please select Financial Income Calculations.")]
public string tempFinancialEarnIncome { get; set; }
}
}
Here is the Controller code
using System;
using System.Configuration;
using System.Linq;
using System.Web.Mvc;
using System.Net;
using System.Data;
using CalFresh.Models;
namespace CalFresh.Controllers
{
public string pubTempHouseHoldSSNVerification;
public string pubtempFinancialEarnIncome;
[HttpPost]
public ActionResult Add(calfreshByWorkUnitID customerinfo)
pubTempHouseHoldSSNVerification = customerinfo.tempHouseHoldSSNVerification;
pubtempFinancialEarnIncome = customerinfo.tempFinancialEarnIncome;
if (ModelState.IsValid)
{
#* Process my insert script here.
}
}

Model state is available in the view via ViewData.ModelState. I don't know what tab library you are using, but somewhere you will need to check which fields are invalid in the model state, figure out which tab they are on, and set focus on that tab.
You should be able to get the fields with errors using something like
ViewData.ModelState.Where(fld => fld.Value.Errors.Count > 0)
or to check individual fields,
ViewData.ModelState.IsValidField("FIELD_NAME")
If you can't set the tab that has focus using css or some sort of tag server side, you'll need to dump the fields with errors into a javascript variable and go from there.
<script>
var errors = '#string.Join(",", ViewData.ModelState.Where(x => x.Value.Errors.Count > 0).Select(fld => fld.Key))';
....
</script>

Related

How to call and execute stored procedures in ASP.Net MVC(C#)

Good day guys, I'm in a little limbo here. I have created my database, model, controller and view in visual studio using ASP.NET MVC and C#, but I can't figure out how to call a stored procedure that I created also.
I want for the stored procedure to be called on a button I placed in my view.
This stored procedure should execute and display results when the button is click.
Below are the Stored procedure, view, model and controller I created.
This is my 'Employee' Model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;
namespace MVCSimpleApp.Models
{
[Table("Employees")]
public class Employee
{
[Display(Name ="Employee Id")]
public int EmployeeId { get; set; }
[Display(Name ="First Name")]
public string FirstName { get; set; }
[Display(Name ="Last Name")]
public string LastName { get; set; }
}
}
This is my Data Context:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace MVCSimpleApp.Models
{
public class EmployeeContext : DbContext
{
public DbSet<Employee> Employee { get; set; }
}
}
This is my Employee Controller:
using MVCSimpleApp.Models;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
namespace MVCSimpleApp.Controllers
{
public class EmployeeController : Controller
{
private EmployeeContext db = new EmployeeContext();
// GET: Employee
public ActionResult Index()
{
var employees = from e in db.Employee select e;
return View(employees);
}
}
}
And now this is my Stored procedure. It is not much, just something for practice purpose.
Create Proc DisplayStudents
AS
BEGIN
/*selecting all records from the table whose name is "Employee"*/
Select * From Employee
END
This is my view:
#model IEnumerable<MVCSimpleApp.Models.Employee>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Student List</h2>
<p>
<a href="#Url.Action("Create")" title="Add new" class="btn btn-primary btn-lg">
<span class="glyphicon glyphicon-plus "></span>
Add Student
</a>
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.EmployeeId)
</th>
<th>
#Html.DisplayNameFor(model => model.FirstName)
</th>
<th>
#Html.DisplayNameFor(model => model.LastName)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(model => item.EmployeeId)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
<span>
<a href="#Url.Action("Edit", new { id = item.EmployeeId})" title="Edit Record">
<span class="glyphicon glyphicon-pencil"></span>
</a>
</span>
|
<span>
<a href="#Url.Action("Details", new { id = item.EmployeeId})" title="View Details">
<span class="glyphicon glyphicon-th-list"></span>
</a>
</span>
|
<span>
<a href="#Url.Action("Delete", new { id = item.EmployeeId})" title="Delete">
<span class="glyphicon glyphicon-trash"></span>
</a>
</span>
</td>
</tr>
}
/*this is the button I want the stored procedure to be called on when I click it*/
<button>Run</button>
</table>
Please guys I need your opinions and feedback on this matter. Will accept tips in passing parameters to a stored procedure. Please correct me if I am not doing things right here. Thanks for your concern.
If using EF is not a necessity you can do it in the following way:
string cnnString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;
SqlConnection cnn = new SqlConnection(cnnString);
SqlCommand cmd = new SqlCommand();
cmd.Connection = cnn;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "ProcedureName";
//add any parameters the stored procedure might require
cnn.Open();
object o = cmd.ExecuteScalar();
cnn.Close();
If you need to use Entity Framework check out this discussion. Also you want to use the Stored Procedures for Inserting, Updating and deleting check out this tutorial from Microsoft.
To execute the code from a button click you can create a form an place just one button inside the form like this:
#using(Html.BeginForm("TestAction", "TestController", FormMethod.Get))
{
<input type="submit" value="Submit" />
}
And in your controller you would have a TestAction method like this
public ActionResult TestAction(){....}
if you need to pass any arguments to TestAction, just specify them as parameters in the method and then use the overloaded version of BeginForm that accepts actionName, controllerName, routeValues and formMethod as arguments.
To pass the results to a view you need to create a view model with properties according to the values you recieve from the stored procedure and then, return a view with the view model from the TestAction method.
Here is an example of how you can do this with entity framework. I personally am not a big fan of entity frameworks because it is slow and clunky, but people with limited DB EXP tend to like it.
Normally I like to give a full example with all the code but due to the way entity frameworks is configured I will pass on that part. Keep in mind this wont work without the entity framework context already being setup.
private RAP_Entities db = new RAP_Entities();
public string GetGUID(string DeviceID, string CCCShopID)
{
SqlParameter[] Parameters =
{
new SqlParameter("#DeviceID", DeviceID),
new SqlParameter("#CCCShopID", CCCShopID)
};
string DistributionChannelGUID = db.Database.SqlQuery<string>("GetDistributionChannelGUID #DeviceID, #CCCShopID", Parameters).ToString();
return DistributionChannelGUID;
}
You can make it through Normal ADO.Net Approach where you call StoredProcedure using SqlCommand and pass few parameters to it.
try
{
conn.Open();
SqlCommand dCmd = new SqlCommand("store_procedure_name",conn);
dCmd.CommandType = CommandType.StoredProcedure;
dCmd.Parameters.Add(new SqlParameter("#parameter2",parameter2));
dCmd.Parameters.Add(new SqlParameter("#parameter1", parameter1));
SqlDataAdapter da = new SqlDataAdapter(dCmd);
DataTable table = new DataTable();
ds.Clear();
da.Fill(ds);
conn.Close();
var das = ds.Tables[0].AsEnumerable();
return ConvertToDictionary(ds.Tables[0]);
}
catch
{
}

Read data from model and display on razor view - mvc

I am trying to get the data from database through model and display it on a view. Here is the sample code, i am able to pull the data but that is not showing up on the view.I appreciate any help. Thanks in advance
Model Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using System.Configuration;
namespace Test.Models
{
public class CustModel
{
SqlConnection con = new SqlConnection();
List<CustModel> CustList = new List<CustModel>();
public String CustName { get; set; }
public String CustPhone { get; set; }
CustModel p = null;
public List< CustModel > GetCustInfo()
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["CustConnectionString"].ToString());
con.Open();
using (con)
{
SqlCommand cmd = new SqlCommand("select * FROM Cust_tb where ZIP = 37771", con);
SqlDataReader rd = cmd.ExecuteReader();
while (rd.Read())
{
p = new CustModel ();
p.CustName =Convert.ToString(rd.GetSqlValue(0));
p.CustPhone = Convert.ToString(rd.GetSqlValue(10));
CustList.Add(p);
}
return CustList;
}
}
}
Controller Code
public ActionResult CustDisplay()
{
CustModel p = new CustModel();
List<CustModel> Li = new List<CustModel>();
Li = p. GetCustInfo ();
ViewData["CustInfo"] = Li;
return View("CustDisplay");
}
View Code
#model Test.Models.CustModel
#{
ViewBag.Title = "CustDisplay";
}
<!DOCTYPE html>
<head>
<title> Customer Information </title>
</head>
<body>
<div class="display-label">
Name
</div>
<div class="display-field">
#Html.DisplayFor(Model => Model.CustName)
</div>
<div class="display-label">
Phone
</div>
<div class="display-field">
#Html.DisplayFor(Model => Model. CustPhone)
</div>
</body>
</html>
Maybe I am over-simplifying this - but I think it is just because you didn't actually send or use your list in the view... I don't get my data the way you did - so I will assume that you are getting the data you want, and the returning list contains 1 to many rows of data in p (name and phone)
even though you pass your list in ViewData - you aren't assigning it in the view.. the best way to do this would be in your controller to call return View(Li); and not return View("CustDisplay"); you are already in the view you want to call - so it will send the list into the #model. (There may be a way to assign the ViewData to the model in the view also) - but I pass the list in, so the data is bound...
You should make the model #model IEnumerable<Test.Models.CustModel>
and then
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.CustName)
</th>
<th>
#Html.DisplayNameFor(model => model.CustPhone)
</th>
</tr>
#foreach (var item in Model){
<tr>
<td>
#Html.DisplayFor(modelItem => item.CustName)
</td>
<td>
#Html.DisplayFor(modelItem => item.CustPhone)
</td>
</tr>
}
</table>

Client validation not showing message

I have a MVC4 internet application with a form for creating user accounts. The form validation works but while the input fails validation no error message is displayed. It still prevents submitting until the validation problem is solved but there is no text
Razor View Form
<h2>Create New Account</h2>
<fieldset>
<legend></legend>
#using (Html.BeginForm("CreateUser",null)){
#Html.AntiForgeryToken()
<table class="create">
<tr>
<td colspan="2"><b>New Account</b>
</tr>
<tr>
<td>#Html.DisplayNameFor(model=>model.UserName)</td><td>#Html.TextBoxFor(model=>model.UserName)</td>
<td>#Html.DisplayNameFor(model=>model.EmailAddress)</td><td>#Html.TextBoxFor(model=>model.EmailAddress)</td>
<td><input type="submit" value="Create User" /></td>
</tr>
</table>
}
</fieldset>
#Html.ValidationSummary()
The bundles used include the validation files
bundles.Add(new ScriptBundle("~/bundles/asset").Include(
"~/Scripts/jquery-{version}.js",
"~/Scripts/jquery-ui-{version}.js",
"~/Scripts/jquery.validate*",
"~/Scripts/jquery.unobtrusive*"));
The Model used is an entity model, I have added a partial class to annotate the validation requirements
[MetadataType(typeof(UserProfileMetadata))]
public partial class UserProfile
{
//Empty Class just required for adding class level attribute
}
public class UserProfileMetadata
{
//Fields from user profile requiring annotations
[EmailAddress]
[Required]
[Display(Name = "Email Address")]
public string EmailAddress { get; set; }
[Required]
public string UserName { get; set; }
}
The validation working but now showing the message makes me think it must be a markup error but I just can't see it.
Moving the ValidationSummary inside the form will fix it.
<h2>Create New Account</h2>
<fieldset>
<legend></legend>
#using (Html.BeginForm("CreateUser",null)){
#Html.ValidationSummary()
#Html.AntiForgeryToken()
<table class="create">
<tr>
<td colspan="2"><b>New Account</b>
</tr>
<tr>
<td>#Html.DisplayNameFor(model=>model.UserName)</td> <td>#Html.TextBoxFor(model=>model.UserName)</td>
<td>#Html.DisplayNameFor(model=>model.EmailAddress)</td><td>#Html.TextBoxFor(model=>model.EmailAddress)</td>
<td><input type="submit" value="Create User" /></td>
</tr>
</table>
}
</fieldset>
For anyone stumbling across this who does not wish to be restricted to moving the #Html.ValidationSummary into the form, i.e. it lives in _Layout.cshtml, and you like it there, here's a way around that.
The below method is apparently what is used by Microsoft to populate #Html.ValidationSummary. In it's standard form, it looks for data-valmsg-summary-true in $('this'). this in this case is the calling form. Well, my #Html.ValidationSummary lives in the pageBody <div> on _Layout.cshtml to keep it DRY.
function onErrors(event, validator) { // '#pageBody' is the containing element
var container = $('#pageBody').find("[data-valmsg-summary=true]"),
list = container.find("ul"); if (list && list.length && validator.errorList.length) {
list.empty(); container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
$.each(validator.errorList, function () {
$("<li />").html(this.message).appendTo(list);
});
}
}
So far, I've only changed this:
var container = $('this').find("[data-valmsg-summary=true]")
to this:
var container = $('#pageBody').find("[data-valmsg-summary=true]")
Now, I trigger my validation from a button click. To get onErrors(event, validator) to fire, I used the following jQuery:
$('#btnSave').click(function () {
if ($('form').valid()) {
// Do stuff
} else {
onErrors(event, $('form').data('validator'));
}
});
Voila, #Html.ValidationSummary populates even when using jQuery.unobtrusive.
A big thanks to Leniel Macaferi for pointing me in the right direction here:
http://www.leniel.net/2013/08/customizing-aspnet-mvc-html-validation-summary-with-bootstrap-3-panel.html#sthash.jGRguVuV.qSjYUlhS.dpbs

Postback on partially loaded view brings null model

My application have page with few search boxes. When user clicks on respective search button a result grid is expected to load. That grid have few editable controls in which user can modifications and hit save button if needed to save the data.
We have implemented the functionality using AjaxForm and partial view.
Search area containing search boxes and search button is created using Ajax.BeginForm, on submit of which a postback Search method is called from controller. SearchModel is passed to this method.
Partial View is created to show results and Ajax form in step 1 loads it successfully from controller postback method. SearchModel.Results property is passed to view as its model.
This partial view showing results have a Save button (again a Ajax form) which invokes another method in controller but gets model null in controller.
have tried lot of tricks but was unsuccessful. Any working example demonstrated anywhere or suggestion to make this working ? There are lot of examples on web where usage of AjaxForm to load data is explained but didn’t found any for multiple (or nested?)
Thanks in advance.
Edit - Feb 24
Here is the sample I created using Visual Studio default MVC template, which is similar to the actual criteria explained above and have the same problem on Submit of Partial page ..
Views:
Index.cshtml
#using MvcApplication1.Models
#model SearchModel
#{
ViewBag.Title = "Home Page";
}
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" ></script>
<h2>#ViewBag.Message</h2>
<p>
To learn more about ASP.NET MVC visit http://asp.net/mvc.
</p>
#Ajax.BeginForm("Search", "Home", new AjaxOptions { HttpMethod = "Post",
InsertionMode = InsertionMode.Replace,UpdateTargetId = "SearchResults"})
{
<table>
<tr>
<td>
First Name:
</td>
<td>
#Html.TextBoxFor(m => m.SearchString)
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit" />
</td>
</tr>
</table>
}
<div id="SearchResults" style="color: Green;"></div>
Partial View - _SearchResult.cshtml
#using MvcApplication1.Models
#model MvcApplication1.Models.SearchModel
#{
ViewBag.Title = "Result Partial";
}
<h2>
testPartial</h2>
#Ajax.BeginForm("SearchResult", "Home", new AjaxOptions
{
HttpMethod = "Post"
})
{
<table>
#foreach (ResultModel item in Model.Result)
{
<tr>
<td>
Name:
</td>
<td>
#Html.DisplayFor(m => item.Name)
</td>
</tr>
<tr>
<td>
Address:
</td>
<td>
#Html.TextAreaFor(m => item.Address)
</td>
</tr>
}
<tr>
<td colspan="2">
<input type="submit" value="Submit" />
</td>
</tr>
</table>
}
Models:
SearchModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcApplication1.Models
{
public class SearchModel
{
public string SearchString { get; set; }
public List<ResultModel> Result { get; set; }
}
}
ResultModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcApplication1.Models
{
public class ResultModel
{
public string Name { get; set; }
public string Address { get; set; }
}
}
Controller:
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
[HttpPost]
public ActionResult Search(SearchModel model)
{
//dummy search for result
List<ResultModel> result = new List<ResultModel>();
ResultModel res1 = new ResultModel();
res1.Name = model.SearchString + " 1";
res1.Address = "Dummy address";
result.Add(res1);
ResultModel res2 = new ResultModel();
res2.Name = model.SearchString + " 2";
res2.Address = "Rummy address";
result.Add(res2);
//assign seach results to model
model.Result = result;
return PartialView("_SearchResult", model);
}
[HttpPost]
public ActionResult SearchResult(SearchModel model)
{
//do something with results
List<ResultModel> res = model.Result; // null here !!
return RedirectToAction("Index");
}
}
}
SO, above sample will
Show you a Search box on home page - Index.cshtml
When you click on submit it will load a partial view displaying results below search
When you edit search results and hit submit on result form, please have a breakpoint set up there, you will see model being returned is null.
Hope, this explain my problem.
Now that you have shown your actual code with a complete example your question can be answered.
The reason you are getting null is because you are not respecting the standard naming convention for your input fields that the default model binder expects. Please read the following article from Phil Haack to familiarize yourself with those conventions.
The problem with your code is the fact that you used a foreach loop inside your partial to render the results instead of using an editor template. So replace your code inside _SearchResult.cshtml with the following:
#using MvcApplication1.Models
#model SearchModel
#{
ViewBag.Title = "Result Partial";
}
<h2>testPartial</h2>
#using(Ajax.BeginForm("SearchResult", "Home", new AjaxOptions()))
{
<table>
#Html.EditorFor(x => x.Result)
<tr>
<td colspan="2">
<input type="submit" value="Submit" />
</td>
</tr>
</table>
}
and then define a custom editor template for the ResultModel type (~/Views/Shared/EditorTemplates/ResultModel.cshtml - warning, the name and location of your editor template is important because it works by convention):
#using MvcApplication1.Models
#model ResultModel
<tr>
<td>
Name:
</td>
<td>
#Html.DisplayFor(m => m.Name)
#Html.HiddenFor(m => m.Name)
</td>
</tr>
<tr>
<td>
Address:
</td>
<td>
#Html.TextAreaFor(m => m.Address)
</td>
</tr>
Things to notice:
I have wrapped the Ajax.BeginForm helper in a using statement. You should do the same inside your Index.cshtml view
I have added a hidden field for the Name property inside the custom editor template (#Html.HiddenFor(m => m.Name)) in order to send this value to the server when the form is submitted because you only had a TextArea for the Address field meaning that the Name would never have been sent to your server.

Asp.net MVC Razor more than one form on a page

Yo
I have a registration page on my site - at the top of the page is a login form for existing users. In the main area there is the registration form.
The login are is a partial view with #model ViewModels.LoginViewModel
The registration are is also a partial with #model ViewModels.RegViewModel
The main page which houses these partials is a view with #model ViewModels.RegPageViewModel
This viewmodel looks like:
public class RegViewModel
{
public RegisterVm RegisterVm { get; set; }
public LoginVm LoginVm { get; set; }
}
When I submit the registration part of the page (it's action is register/capture - the receiving action expects a RegisterVm) to it's controller it complains about being passed the wrong viewmodel
What's the deal with subviews and their viewmodel? Is there a standard approach to dealing with this?
Should I have one submit URL for this page which figures out if it's a login request or a register request and then handles the post accordingly? That seems messy to me though...
http://monobin.com/__d33cf45a4 - RegisterVm.cs (LoginVm.cs is pretty much the same as this)
http://monobin.com/__m69132f76 - RegPageVm.cs
Register.cshtml:
#model xxxx.ViewModels.RegPageVm
#{
View.Title = "Register";
Layout = "~/Views/Shared/_BareBones.cshtml";
}
<link rel="stylesheet" href="#Url.Content("~/Public/Css/signup.css")" type="text/css" />
<div id="sign-up-container">
<div id="sign-up-box">
<div id="sign-up-box-left">
<img src="#Url.Content("~/Public/Images/Signup_176x81.png")" />
</div>
<div id="sign-up-box-right">
#Html.Partial("_Register")
</div>
</div>
</div>
<div class="clear">
</div>
_Register.cshtml:
#model xxxx.ViewModels.RegisterVm
#using (Html.BeginForm("Capture", "Register", FormMethod.Post))
{
<table class="sign-up-box-inner">
<tr>
<td class="label-area">
#Html.LabelFor(x => x.Email)
</td>
<td class="field-area">
#Html.TextBoxFor(x => x.Email, new { #class = "login-input", title = "Enter Name" })
</td>
</tr>
<tr>
<td class="label-area">
#Html.LabelFor(x => x.Password)
</td>
<td class="field-area">
#Html.PasswordFor(x => x.Password, new { #class = "login-input", title = "Enter Name" })
</td>
</tr>
<tr>
<td class="label-area">
#Html.LabelFor(x => x.UserName)
</td>
<td class="field-area">
#Html.TextBoxFor(x => x.UserName, new { #class = "login-input", title = "Enter Name" })
</td>
</tr>
<tr>
<td colspan="2">
<input type="image" src="../../Public/Images/Submit_150x47.png" class="submit-button" />
</td>
</tr>
</table>
#Html.AntiForgeryToken()
}
And finally RegisterController.cs:
public class RegisterController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Capture(RegisterVm registerVm)
{
if (!ModelState.IsValid)
{
return View("index", new RegPageVm()
{
LoginVm = new LoginVm(),
RegisterVm = registerVm
});
}
return RedirectToAction("index", "Event");
}
}
w://
You need to ensure that the form elements (like the textbox etc) should have the same id as the RegisterVM and LoginVM properties. Your theory is right but I think you might be making a mistake in the naming convention of MVC.
If you can share your view code + the VM classes, then we'll be able to help better.
EDIT:
Looking at your code I think you should be passing the view model to your partial view. Like for example the following line believe should be like this >
#Html.Partial("_Register", Model.RegisterVm)
According to your answer to nEEbz:
You are using:
Html.TextBoxFor(x=>x.LoginVM.Email) // i guess
this would turn into <input name="LoginVM.Email" ...>
Notice the LoginVM. part
Your login action probably looks like:
public ActionResult Login(LoginVM model) { }
so it expect field names like Email and Password, not LoginVM.Email and LoginVM.Password.
So you could could use Html.Textbox instead (so that the field name doesn't get autocreated).

Resources