how to validate telerik mvc grid using remote attribute in data annotations? - asp.net-mvc-3

I want to check if username already exists in database using telerik mvc grid (batch edit). But The problem is in order to validate it, I need to pass applconst_id as a parameter in CheckDuplicateType function. But it always return "undefined", I don't know how to get the right value.
this is my model class:
public class masterTypeCont
{
[Key]
public Int32 applconst_id { get; set; }
[Required(ErrorMessage = "This field needs a value!")]
[Remote("CheckDuplicateType",
"Type",
AdditionalFields = "applconst_id",
ErrorMessage = "Code already exists.")]
public String note1 { get; set; }
}
and this is my controller:
[HttpGet]
public virtual JsonResult CheckDuplicateType(masterTypeCont tipe, String applconst_id)
{
Int32 intID = Convert.ToInt32(applconst_id);
return Json(typeEnt.ValidateCustomer(intID, tipe.note1), JsonRequestBehavior.AllowGet);
}
And this is ValidateCustomer function:
public bool ValidateCustomer(Int32 id, String nama) {
Int32 x = db.appl_const.Where(a =>
a.group_id == "CH_COMP_CODE" &&
a.note1.Trim() == nama.Trim() &&
a.applconst_id != id).Count();
Boolean res = x == 0 ? true : false;
return res;
}
This is my view:
#{
ViewBag.Title = "Type List";
Layout = "../Shared/_Layout.cshtml";
}
<div class="direct-content">
#using (Html.BeginForm())
{
#(Html.Telerik().Grid<ComplaintHandling.Models.masterTypeCont>()
.Name("TypeGrid")
.Localizable("id-ID")
.ToolBar(commands =>
{
commands.Insert();
commands.SubmitChanges();
})
.DataKeys(keys => keys
.Add(o => o.applconst_id)
.RouteKey("applconst_id"))
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("_SelectAllType", "Type")
.Update("_SaveBatchType", "Type");
})
.Columns(columns =>
{
columns.Bound(o => o.applconst_id).Hidden();
columns.Bound(o => o.note1).Title("Name");
columns.Command(commands =>
{
commands.Delete().ButtonType(GridButtonType.Text);
}).Title("Command");
})
.ClientEvents(events => events
.OnEdit("OnEditGrid")
)
.Editable(editing => editing.Mode(GridEditMode.InCell))
.Selectable()
.Pageable(pager => pager.PageSize(15))
.Filterable()
.Sortable()
.Scrollable(x => x.Height("450px"))
.KeyboardNavigation()
.Resizable(x => x.Columns(true))
)
<input type="hidden" name="applconst_id" id="applconst_id" value="1">
}
</div>
I write hidden input there to contains the applconst_id, but still it value doesn't passed to controller.
Sorry for my bad english.
Any help will be deeply appreciated.
Thanks.

Try like this:
[HttpGet]
public virtual ActionResult CheckDuplicateType(masterTypeCont tipe)
{
var result = typeEnt.ValidateCustomer(tipe.applconst_id, tipe.note1);
return Json(result, JsonRequestBehavior.AllowGet);
}

Thanks for the answers before.
After doing some research, I finally found solution for my own problem.
I create a little trick there, maybe this isn't a good way, but at least it can solve my problem.
Basically, I just play with the name attribute of an element so that it value can be passed to controller.
Here, I will explain in detail how I've done this.
First, I changed Grid columns in my View to be like this:
Please concern on applconst_id hidden field. I add client template there.
columns.Bound(o => o.applconst_id).Hidden()
.ClientTemplate("<input class='typeID' name='common_id' value='<#= applconst_id #>'>");
columns.Bound(o => o.note1).Title("Nature of complaint");
Second, I add this code in "onEdit" function:
//this code change ID that is being edited, so that it can be passed to controller
var $inputID = $('.t-grid-edit-cell').prev().find('.typeID');
$inputID.attr('name', 'applconst_id');
//change back ID that is not being edited, so that it's not passed to controller
$('td:not(.t-grid-edit-cell)').prev().find('.typeID').attr('name','common_id');
Third, this is my controller:
[HttpGet]
public JsonResult CheckDuplicateType(String applconst_id, String note1)
{
Int32 IntID = Convert.ToInt32(applconst_id);
return Json(typeEnt.ValidateCustomer(IntID, note1), JsonRequestBehavior.AllowGet);
}
And my "ValidateCustomer" function stay the same.
I hope my solution can help other people who have the same problem with me.
Thanks.
Regards,
L.W.

Related

How do I make a Kendo UI batch grid that uses dervied objects on a CSLA framework

What I'm attempting to do is have a "Super" entity class for saved products. Depending on where the product is in the application, certain extra attributes are necessary (but not always).
For example, when the product is being used within a grid, I want to have a ViewModel that derives from the Entity (inheriting all of the common fields) and then add a unique identifier attribute like "rowNumber" for easy searching by the kendo ui grid CRUD.
I thought I had all of this working, but I've hit a snag... Everything renders fine and operates correctly until I click "save" for the batch grid. It executes the function and all the data is present, but when it returns from the CRUD, it breaks. In firebug, I see that an exception is being thrown, but it never finishes (the ajax spinner stays there) and all information within the exception is empty...
I'm not sure if this is some issue with c# not playing well with CSLA or not. I'm unsure.
Any help would be appreciated! I can't upload images because my rep isn't high enough or else I would put a picture of the exception, but I'll at least put what appears in the Firebug console. Everything else about it is empty though...
Exception with endless execution and no response:
GET http://localhost:32574/Exception/SystemException/00000000-0000-0000-0000-000000000000
Entity:
This file is auto-generated by a CodeSmith template so it is kind of nonsensical, but it holds field values that appear in the view (see below). The exception to what is on the view vs what is in the entity are fields that are not 'flattened' in the entity, as Kendo UI does not currently support this inside of editable grids.
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace Project.MVC.Models
{
//The MetaData Class is where to put all annotations and validations
[MetadataType(typeof(Project.Business.Shipment.ItemMetaDataClass))]
public class ItemModel : Project.Business.Shipment.Item
{
public ItemModel()
{
}
public long rowNumber { get; set; }
public decimal Length { get; set; }
public decimal Width { get; set; }
public decimal Height { get; set; }
[Display(Name = "UoMDim")]
[UIHint("ItemGrid_RefUnitOfMeasurementListingDimension")]
public string DimensionUnitOfMeasure { get; set; }
[Display(Name = "UoMW")]
[UIHint("ItemGrid_RefUnitOfMeasurementListingWeight")]
public string WeightUnitOfMeasure { get; set; }
[Display(Name = "Weight")]
public decimal WeightValue { get; set; }
[Display(Name = "Type")]
[UIHint("ItemGrid_RefUnitTypeListing")]
public string QuantityUnitOfMeasure { get; set; }
[Display(Name = "Units")]
public decimal QuantityValue { get; set; }
}
}
Grid Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Kendo.Mvc.UI;
using Kendo.Mvc.Extensions;
namespace Project.MVC.Controllers
{
[Authorize]
public class ItemGridController : Csla.Web.Mvc.Controller
{
public ActionResult GetProducts([DataSourceRequest]DataSourceRequest request)
{
Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;
return Json(shipmentModel.ItemModelList.ToDataSourceResult(request));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateProducts([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<Models.ItemModel> itemsToAdd)
{
Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;
var results = new List<Models.ItemModel>();
if (ModelState.IsValid)
{
foreach (Models.ItemModel newItem in itemsToAdd)
{
if (shipmentModel.ItemModelList.Count > 0)
{
var nextID = (from i in shipmentModel.ItemModelList
select i.rowNumber).Max() + 1;
newItem.rowNumber = nextID;
}
shipmentModel.ItemModelList.Add(newItem);
results.Add(newItem);
}
}
return Json(results.ToDataSourceResult(request, ModelState));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateProducts([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<Models.ItemModel> itemsToUpdate)
{
Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;
var results = new List<Models.ItemModel>();
foreach (var item in itemsToUpdate)
{
Models.ItemModel target = shipmentModel.ItemModelList.Find(i => i.rowNumber == item.rowNumber);
if (target != null)
{
target = item;
}
}
return Json(ModelState.ToDataSourceResult());
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult DeleteProducts([DataSourceRequest]DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<Models.ItemModel> itemsToDelete)
{
Project.MVC.Models.ShipmentModel shipmentModel = (Project.MVC.Models.ShipmentModel)ControllerBase.State.Object;
foreach (var item in itemsToDelete)
{
shipmentModel.ItemModelList.Remove(item);
}
return Json(ModelState.ToDataSourceResult());
}
}
}
View:
#model Project.MVC.Models.ShipmentModel
#using Kendo.Mvc.UI
#(Html.Kendo().Grid<Project.MVC.Models.ItemModel>()
.Name("QuoteItemGrid")
.Columns(columns =>
{
columns.Bound(i => i.FreightClass)
.EditorTemplateName("ItemGrid_RefFreightClassListing")
.Width(50);
columns.Bound(i => i.Length).Width(30);
columns.Bound(i => i.Width).Width(30);
columns.Bound(i => i.Height).Width(30);
columns.Bound(i => i.DimensionUnitOfMeasure)
.EditorTemplateName("ItemGrid_RefUnitOfMeasurementListingDimension")
.Width(50);
columns.Bound(i => i.QuantityValue).Width(30);
columns.Bound(i => i.QuantityUnitOfMeasure)
.EditorTemplateName("ItemGrid_RefUnitTypeListing")
.Width(50);
columns.Bound(i => i.WeightValue).Width(30);
columns.Bound(i => i.WeightUnitOfMeasure)
.EditorTemplateName("ItemGrid_RefUnitOfMeasurementListingWeight")
.Width(50);
columns.Bound(i => i.NmfcCode).Width(50);
columns.Bound(i => i.ItemDescription).Width(100);
columns.Command(command =>
{
command.Destroy();
}).Width(60);
})
.ToolBar(toolbar =>
{
toolbar.Create();
toolbar.Save();
})
.Editable(editable => editable.Mode(GridEditMode.InCell).CreateAt(GridInsertRowPosition.Bottom))
.Pageable()
.Sortable()
.Scrollable()
.Resizable(resize => resize.Columns(true))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(false)
.Events(events => events.Error("QuoteItemGrid_ErrorHandler"))
.Model(model =>
{
model.Id(i => i.rowNumber);
model.Field(i => i.DimensionUnitOfMeasure).DefaultValue("in");
model.Field(i => i.WeightUnitOfMeasure).DefaultValue("lbs");
})
.Create(create => create.Action("CreateProducts", "ItemGrid"))
.Read(read => read.Action("GetProducts", "ItemGrid"))
.Update(update => update.Action("UpdateProducts", "ItemGrid"))
.Destroy(destroy => destroy.Action("DeleteProducts", "ItemGrid"))
)
)
I agree entirely. Ideally your CSLA .NET based objects are domain objects, not data objects, and so match the shape needed by the business requirements not by database tables or queries.
Sadly a lot of people end up (mis)using CSLA like an ORM and so have data-centric objects, thus missing a lot of the value of the framework, and necessitating the creation and maintenance of overly complex viewmodel types in addition to what (should have been) business types.
From an architectural perspective, my group ultimately thought it unwise to tie our database generated entities so closely to our view. Especially now that the project is being used in multiple places (.Net application, Webservices application, etc...).
So, in the end we ended up creating ViewModels for each entity so that we could be flexible with our entities across multiple platforms. This restructuring removed the issue above, as the entities are now never present within the view.
word of caution however: If you're using Kendo UI, you'll have to 'flatten' your view models that you want presented within a singular component that are deep objects (e.g. object within another object). At the moment, Kendo does not support this. We are using ValueInjecter.
Hopefully, this information will help someone else too.

MVC3 DropDownListFor not populating selectedValue

I feel like I'm taking crazy pills. I have a dropdownlist for a view that reads from our database all of the wine producers we have. I want to set the selectedValue to a particular ID driven by the referring page. I can see it picks up the selectedValue in debug, I see the selected value populated (906 for this example), but it doesn't set the dropdownlist to the correct value when the page is rendered, it always defaults to 1 for the default value. I've tried creating the selectList in razor as opposed to my controller, but nothing works. Any help on this would be appreciated, I'm guessing it is something small.
Controller:
if (User.IsInRole("admin"))
{
if (ID != 0)
{
ViewBag.ProducerSelect = new SelectList(db.Producers.OrderBy(p => p.Name), "ProducerID", "Name", ID);
}
else
{
ViewBag.ProducerSelect = new SelectList(db.Producers.OrderBy(p => p.Name), "ProducerID", "Name");
}
}
View:
if (User.IsInRole("producereditor"))
{
<h3>#ViewBag.ProducerName</h3>
}
else
{
<div class="editor-label">
#Html.LabelFor(m => m.Wine.ProducerID, "Producer")
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.Wine.ProducerID, ViewBag.ProducerSelect as SelectList)
</div>
}
Tried the below but no success:
ViewBag.ProducerSelect = new SelectList(from p in db.Producers
orderby p.Name
select new { p.ProducerID, p.Name }
, "ProducerID", "Name", ID);
If you want to preselect an item, You set that value to your ProducerId property.
var yourViewModelObj=new YourViewModel;
yourViewModelObj.Wine.ProducerId=906; //or whatever value you want
return View(yourViewModelObj);
Suggestion : For better code readablity/Maintenance, Try to avoid ViewBag / ViewData and use a ViewModel to pass the data.
I would add a Property to my ViewModel to hold the Collection of Producers
public class WineViewModel
{
//Other Existing properties also
public IEnumerable<SelectListItem> Producers{ get; set; }
public string SelectedProducer { get; set; }
}
Then in yout GetAction method, you can set the value like this, If you want to set one select option as the default selected one.
public ActionResult CreateWine()
{
var vm=new WineViewModel();
//The below code is hardcoded for demo. you mat replace with DB data.
vm.Producers= new[]
{
new SelectListItem { Value = "1", Text = "Prodcer A" },
new SelectListItem { Value = "2", Text = "Prodcer B" },
new SelectListItem { Value = "3", Text = "Prodcer C" }
};
//Now let's set the default one's value
vm.SelectedProducer = "2";
return View(vm);
}
And in your Strongly typed View,
#Html.DropDownListFor(x => x.SelectedProducer,
new SelectList(Model.Producers, "Value", "Text"), "Select Producer")
The HTML Markup generated by above code will have the HTML select with the option with value 2 as selected one.
I figured this out. I had ViewModel.wine.ProducerID elsewhere on the page in a hidden field, and that defaults to 1, so I just assigned that to passed in value, and it worked great. I knew it was something like that. Thanks!
User a ViewModel ex WineViewModel
public class WineViewModel
{
public Wine Wine { get; set; }
public SelectList PProducerList { get; set; }
public WineViewModel() { }
public WineViewModel(Wine wine)
{
this.Wine = wine;
}
}
Try the following in your controller
var model = new WineViewModel( selectwine);
model.ProjectTypeList = new SelectList( from p in db.Producers
orderby p.Name
select new { p.ID, p.Name }, "ID", "Name")
notice how I am exclusively declaring which is the ID and which is the Value in my SelectList
Then in your view do
#Html.DropDownListFor(model => model.Wine.ProducerID, Model.ProjectTypeList)

Custom data binding with Teleriks Grid

I have an MVC3 Telerik app. This is my controller:
[GridAction]
public ActionResult Index(GridCommand command)
{
IEnumerable<Order> data = GetData(command);
var dataContext = new NorthwindDataContext();
//Required for pager configuration
ViewData["total"] = dataContext.Orders.Count();
return View(data);
}
[GridAction(EnableCustomBinding = true)]
public ActionResult _CustomBinding(GridCommand command)
{
IEnumerable<Order> data = GetData(command);
var dataContext = new NorthwindDataContext();
return View(new GridModel
{
Data = data,
Total = dataContext.Orders.Count()
});
}
//Utility method which does custom paging and sorting using Linq
private static IEnumerable<Order> GetData(GridCommand command)
{
var dataContext = new NorthwindDataContext();
IQueryable<Order> data = dataContext.Orders;
if (command.PageSize > 0)
{
data = data.Skip((command.Page - 1) * command.PageSize);
}
data = data.Take(5);
return data;
}
This is my razor View:
#model IEnumerable<Telerik.Order>
#(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(o => o.OrderID).Width(100);
columns.Bound(o => o.Customer.ContactName).Width(200);
columns.Bound(o => o.ShipAddress);
columns.Bound(o => o.OrderDate).Format("{0:MM/dd/yyyy}").Width(100);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax().Select("_CustomBinding", "Home").Enabled(true);
})
.Pageable(pager => pager.Total((int)ViewData["total"]))
.EnableCustomBinding(true)
.Sortable()
)
When I run the app, it loads fine, but when I click on a number in the paging row at the bottom, I get :
Error! The requested URL returned 500- Internal server error
It calls my function _CustomBinding and doesnt throw an error when i step through it. Whats causing this error?
This means that a server side exception has occurred in _CustomBinding method. You can check what the actual server response is - it would contain the stacktrace. Use Fiddler or your browser's developer tools to check what the server response is.

EditorFor on nullable DateTime - "Nullable object must have a value."

I am attempting to display a form that allows a user to input a new assignment for a person. I'm using a DateTime.cshtml EditorTemplate to handle DateTime values for the assignment. The non-nullable DateTime works fine. The nullable DateTime causes an "InvalidOperationException: Nullable object must have a value."
I have a simple viewmodel that looks like this:
AssignmentViewModel.cs:
public Person Person { get; set; }
public Assignment NewAssignment { get; set; }
Assignment.cs contains:
public DateTime AssignmentStartDate { get; set; }
public DateTime? AssignmentEndDate { get; set; }
My AssignmentController Create() method looks like:
public ViewResult Create(int personId)
{
Person person = personRepository.GetPersonById(personId);
var newAssignment = new AssignmentViewModel { Person = person, NewAssignment = new Assignment() };
return View(newAssignment);
}
My Create.cshtml view looks like this:
#model AssignmentViewModel
#using (Html.BeginForm("Create", "Assignment"))
{
#Html.Hidden("NewAssignment.PersonId", Model.Person.PersonId)
#Html.LabelFor(x => x.NewAssignment.AssignmentStartDate):
#Html.EditorFor(x => x.NewAssignment.AssignmentStartDate.Date, new { cssClass = "datePicker" })
<br />
#Html.LabelFor(x => x.NewAssignment.AssignmentEndDate):
#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate.Value.Date, new { cssClass = "datePicker" })
<br />
<input type="submit" value="Send />
}
My DateTime.cshtml EditorTemplate looks like:
#model DateTime?
#{
String modelValue = "";
if (Model.HasValue)
{
if (Model.Value != DateTime.MinValue)
{
modelValue = Model.Value.ToShortDateString();
}
}
}
#Html.TextBox("", modelValue, new { #class = "datePicker" })
When I attempt to load the Create view, I get the exception mentioned above on the line "#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate.Value)".
You may be wondering why I'm passing in AssignmentEndDate.Value.Date instead of just passing in AssignmentEndDate; the reason is because I'm trying to get to the point where I'm splitting DateTime into Date and a TimeOfDay field and recombine them with a DateTimeModelBinder. I am using a similar technique to the one shown here and here.
I -can- bypass the error, by changing my controller Create() method to instantiate the ViewModel with AssignmentEndDate set to DateTime.MinValue, but this seems completely wrong for a nullable DateTime:
var newAssignment = new AssignmentViewModel
{
Person = person,
NewAssignment = new Assignment { AssignmentEndDate = DateTime.MinValue }
};
Something strange happens after I "bypass" the error by supplying a value for the nullable DateTime; the un-required nullable DateTime property (AssignmentEndDate.Date) fails client side validation. Trying to submit the form highlights the field in red.
How can I handle this correctly?
The problem is that you're trying to retrieve the AssignmentEndDate.Value.Date, but AssignmentEndDate is null, which results in this error.
Since your editor template accepts a DateTime?, you should just pass along the AssignmentEndDate. In other words, remove the .Value.Date from the view:
#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate, new { cssClass = "datePicker" })
Since your editor template is using ToShortDateString(), there's no need to "truncate" the time from the date at all.
Update
Regarding your desire to have separate "Date" and "Time" editors:
You can do this 2 ways.
1 - Your current DateTime? editor renders a field for the Model.Value.Date, so you could simply extend this to also render a field for the Model.Value.TimeOfDay. Example:
#{
DateTime? modelDate = (Model == null) ? (DateTime?)null : Model.Value.Date;
TimeSpan? modelTime = (Model == null) ? (TimeSpan?)null : Model.Value.TimeOfDay;
}
#Html.TextBox(..., modelDate, new{#class="datePicker"})
#Html.TextBox(..., modelTime, new{#class="timePicker"})
2 - You could split the above functionality into 2 separate editors, "DateOnly" and "TimeOnly". Then, update your view to call both editors:
#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate, "DateOnly")
#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate, "TimeOnly")
The choice is up to you, and whether you want to keep the Date and Time parts separate or together, but this is how I'd go about solving this problem.
create a DateTime.cshtml in your Shared/DisplayTemplate folder
#model Nullable<DateTime>
#(Model != null ? string.Format(ViewData.ModelMetadata.DisplayFormatString ?? "{0:d}", Model) : string.Empty)
this supports metadata from datannotations to be used if found.
UPDATE: GetValueOrDefault treats it as a DateTime and therefore the required Field validators are getting attached, because the original expression is for a datetime not a nullable datetime.
Therefore the solution below doesn't work.
Like the asker, I also used the DateTimeModelBinder from here:
Here's the Link
This is how I solved a similar situation:
#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate.GetValueOrDefault().Date)
And this is what my DateTime EditorTemplate looks like:
#model DateTime
#Html.TextBox("", Model != default(DateTime) ? Model.ToShortDateString() : String.Empty, new { #class = "datepicker", #maxlength = "10" })

Form for a different model than the view page in ASP.NET MVC 3

I have Results page that contains an signup form. I'm trying to use client-side validation on the email model, but I can't because the model type is different than the type I'm posting.
class Results
{
... // some results data to display
}
class EmailSignup
{
public virtual int Id { get; set; }
[Required(ErrorMessage = "Please enter your email.")]
[DataType(DataType.EmailAddress)]
[RegularExpression(#"^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+#((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$", ErrorMessage = "Please enter a valid email address.")]
public virtual string Email { get; set; }
}
Results.cshtml
#model MyApp.Results
[display results]
...
#using (Html.BeginForm("SubmitEmail", "AnalysisResults", FormMethod.Post))
{
<fieldset>
#Html.TextBoxFor( model => model.???? )
</fieldset>
}
The type I want the user to submit is EmailSignup, not Results.
Move the form to a partial view that takes an EmailSignup model.
This can be done quite easily. You just have to do it like this:
var contactModel = new ContactModel();
#Html.TextBoxFor(m => contactModel.Title)
#Html.ValidationMessageFor(m => contactModel.Title)
The validation works like a charm.
I have find out 2 more ways
Override the Name attribute for TextBoxFor and set it as the property name.
var formModel = new ForgotPasswordFormModel();
#Html.TextBoxFor(m => formModel.UsernameOrEmail, new { Name = "UsernameOrEmail" })
Specify the same exact model name as the post method parameter.
var formModel = new ForgotPasswordFormModel();
#using (Html.BeginForm("ChangePassword", "LoginSurface")
{
#Html.TextBoxFor(m => formModel.UsernameOrEmail)
}
...
public virtual ActionResult ChangePassword(ForgotPasswordFormModel formModel)
You could create another HtmlHelper like this
var emailSignupHtml = new HtmlHelper<EmailSignup>(Html.ViewContext, new ViewDataContainer<EmailSignup>(new EmailSignup()));
and use it like this
#emailSignupHtml.TextBoxFor(m => m.Email)
For the ViewDataContainer I use following helper class
public class ViewDataContainer<TModel> : ViewDataDictionary<TModel>, IViewDataContainer
{
public ViewDataContainer(TModel model) : base (model)
{
ViewData = new ViewDataDictionary(model);
}
public ViewDataDictionary ViewData { get; set; }
}
I guess you can also try #HTML.Action("EmaialSignup")
and your controller will have a Function calling the partial view
if you have to render multiple model bounded View in this view

Resources