Get full name of Complex Type from ModelClientValidationRequiredIfRule method in custom ValidationAttribute - asp.net-mvc-3

I am using the example at The Complete Guide To Validation In ASP.NET MVC 3 to create a RequiredIf validation attribute (it's about 1/3 down the page under the heading of "A more complex custom validator"). It all works fine with the exception of one scenario, and that is if I have the need to validate against a complex type. For example, I have the following model:
public class MemberDetailModel
{
public int MemberId { get; set; }
// Other model properties here
public MemberAddressModel HomeAddress { get; set; }
public MemberAddressModel WorkAddress { get; set; }
}
public class MemberAddressModel
{
public bool DontUse { get; set; }
// Other model properties here
[RequiredIf("DontUse", Comparison.IsEqualTo, false)]
public string StreetAddress1 { get; set; }
}
The problem is that when the attribute validation for the StreetAddress property is rendered, it get's decorated with the attribute of data-val-requiredif-other="DontUse". Unfortunately, since the address is a sub-type of the main model, it needs to be decorated with a name of HomeAddress_DontUse and not just DontUse.
Strangely enough, the validation works fine for server-side validation, but client-side unobtrusive validation fails with an JS error because JS can't find the object with a name of just "DontUse".
Therefore, I need to find a way to change the ModelClientValidationRequiredIfRule method to know that the property it is validating is a sub-type of a parent type, and if so, prepend the ParentType_ to the "otherProperty" field (e.g. otherProperty becomes HomeAddress_DontUse.
I have tried passing in typeof(MemberAddressModel) as a parameter of the attribute, but even when debugging the attribute creation, I can't seem to find any reference to the parent type of HomeAddress or WorkAddress from that type.

Based on the suggestion from The Flower Guy, I was able to come up with the following which seems to work. I simply modified the following in the customValidation.js file:
jQuery.validator.addMethod("requiredif", function (value, element, params) {
if ($(element).val() != '') return true;
var prefix = getModelPrefix(element.name); // NEW LINE
var $other = $('#' + prefix + params.other); // MODIFIED LINE
var otherVal = ($other.attr('type').toUpperCase() == "CHECKBOX") ? ($other.attr("checked") ? "true" : "false") : $other.val();
return params.comp == 'isequalto' ? (otherVal != params.value) : (otherVal == params.value);
});
I also added the following method to that file (within the JQuery block so as to be only privately accessible):
function getModelPrefix(fieldName) {
return fieldName.substr(0, fieldName.lastIndexOf(".") + 1).replace(".","_");
}

Cannot do it exactly right now, but the problem is in the client javascript function:
jQuery.validator.addMethod("requiredif" ...
The js is not sophisticated enough to cope with complex view models where there may be a model prefix. If you take a look at Microsoft's jquery.validate.unobstrusive.js (in the Scripts folder over every MVC3 application), you will find some useful methods including getModelPrefix and appendModelPrefix. You can take a similar approach and change the requiredIf validation method - take a look at the equalto method in jquery.validate.unobstrusive.js for a helping hand.

Related

Validation for items in ObservableCollection bound to DataGrid when validation of one item of collection depends on other items

I am using MVVM and displaying some items on a DataGrid. My model is RecordingInfo and looks like:
public class RecordingInfo : IDataErrorInfo
{
public RecordingInfo(string fullDirectoryName, string recordingName, int recordingNumber)
{
FullDirectoryName = fullDirectoryName;
RecordingName = recordingName;
RecordingNumber = recordingNumber;
}
public string FullDirectoryName { get; internal set; }
public string RecordingName { get; set; }
public int RecordingNumber { get; internal set; }
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string propertyName]
{
get {
if (propertyName == "RecordingName")
{
if (this.RecordingName.Length < 2)
return "Recording Name must be at least two characters";
}
return null;
}
}
}
I end up with a collection of these RecordingInfo programmatically. The user is not allowed to do much with these but he/she can change the RecordingName subject to the name being 2 characters or more AND that the RecordingName must be unique. I.e. no changing it to match another RecordingName. I have taken care of the first requirement. It's the second one that is giving me grief.
For my ViewModel, I have
public class RecordingListViewModel : ViewModelBase//, IDataErrorInfo
{
private ObservableCollection<RecordingInfo> _recordings = null;
public RecordingListViewModel()
{
}
public ObservableCollection<RecordingInfo> Recordings
{
get
{
return _recordings;
}
}
// more stuff left off for brevity
In my view I bind the collection to a DataGrid and have:
<DataGrid ItemsSource="{Binding Path=Recordings}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Recording" IsReadOnly="False" EditingElementStyle="{StaticResource CellEditStyle}" ElementStyle="{StaticResource CellNonEditStyle}" Binding="{Binding RecordingName, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" >
</DataGridTextColumn>
...
</DataGrid.Columns>
My way of checking for 2 or more characters works great. But this doesn't work for checking that the user is not trying to give a recording an existing name. Presumably, I need to somehow handle this at the ViewModel layer since the ViewModel knows about all Recordings. I tried playing with having my ViewModel derive from IDataErrorInfo but the property indexer never gets called, which makes sense as it's the Observable collection and therefore the individual RecordingInfos that are bound. I also thought about doing something with a "Lost Focus" event, but DataGridTextColumn doesn't seem to have that. I would think this is a somewhat common problem: validation must take into account relationships between the items of the collection.
By the way, I'm not wedded to the IDataErrorInfo and I am not opposed to other changes in architecture. Please let me know if I can provide more details. I have tried to provide a minimal amount of code. Clearly, this is part of a much bigger project. Any advice is appreciated.
Thanks,
Dave
I would do the following
1) Make RecordingInfo implement INotifyPropertyChanged
2) Use a BindingList<> instead of ObservableCollection<>
In your viewmodel, subscribe to the BindingList.ListChanged Event. This event will fire when items are added and removed, but also when the top level properties on RecordingInfo changes. In the case of a property being changed, the ListChangedEventArgs.PropertyDescriptor property will contain the name of the property, if you want to run validation for just that property (be careful though, this can be null when the item as added/removed). You'll need to use the ListChangedType property to determine the reason of the event (E.x.: Reset means everything changed, ItemAdded means the item was added, but the ItemChanged means a property changed as occurred on an existing item.
You can have the parent ViewModel (that contains and creates your RecordingInfos) pass a name validation Func in their constructors for them to call when validating their name changes.

The model item passed into the dictionary is of type 'Sitecore.Mvc.Presentation.RenderingModel', but this dictionary requires a model item of type 'X'

I am building a solution with Sitecore 7 and ASP.NET-MVC 3 and trying to use a custom model class as described in this blog post by john west.
I have seen several other questions here on SO reporting a similar error with ASP.NET-MVC (without Sitecore), usually related to passing the wrong type of object in controller code, or there being a configuration error with the \Views\web.config file, but neither seem to be the issue here.
this issue is caused when you create a view rendering (possibly others but i haven't tried it) and you have not set up the model in sitecore, so sitecore is passing in its default model.
To fix this you have to go to the layouts section and create a model.
this is the path in sitecore '/sitecore/layout/Models/', in this folder create a 'Model' item and in the model type field you add the reference to your model in the format 'my.model.namespace, my.assembly' without the quotes.
your model needs to inherit 'Sitecore.Mvc.Presentation.IRenderingModel' which forces you to implement the 'Initialize' method, in here you populate data from the sitecore item into the properties of the model. here is an example model...
namespace Custom.Models.ContentBlocks
{
using Sitecore.Data.Fields;
using Sitecore.Mvc.Presentation;
public class BgImageTitleText : IRenderingModel
{
public string Title { get; set; }
public string BgImage { get; set; }
public string BgImageAlt { get; set; }
public string BgColour { get; set; }
public string CtaText { get; set; }
public string CtaLink { get; set; }
public void Initialize(Rendering rendering)
{
var dataSourceItem = rendering.Item;
if (dataSourceItem == null)
{
return;
}
ImageField bgImage = dataSourceItem.Fields[Fields.ContentBlocks.BgImageTitleTextItem.BgImage];
if (bgImage != null && bgImage.MediaItem != null)
{
this.BgImageAlt = bgImage.Alt;
this.BgImage = Sitecore.Resources.Media.MediaManager.GetMediaUrl(bgImage.MediaItem);
}
var title = dataSourceItem.Fields[Fields.ContentBlocks.BgImageTitleTextItem.Title];
if (title != null)
{
this.Title = title.Value;
}
var link = (LinkField)dataSourceItem.Fields[Fields.ContentBlocks.BgImageTitleTextItem.CtaLink];
if (link != null)
{
this.CtaLink = link.GetLinkFieldUrl();
}
var ctaText = dataSourceItem.Fields[Fields.ContentBlocks.BgImageTitleTextItem.CtaText];
if (ctaText != null)
{
this.CtaText = ctaText.Value;
}
var bgColour = dataSourceItem.Fields[Fields.ContentBlocks.BgImageTitleTextItem.BgColour];
if (bgColour != null)
{
this.BgColour = bgColour.Value;
}
}
}
}
Then you have to go to your view rendering (or possibly other types of rendering) and in the 'Model' field you click insert link and click on your newly created model.
This error can be caused when a controller rendering invokes a controller method which returns an ActionResult object instead of a PartialViewResult. In my case I had a rendering model associated with the layout which I believe Sitecore was trying to pass to my controller rendering.
RenderingModel is used when you create a Rendering based on the View Rendering template. This model is created by the sitecore MVC pipelines and is automatically assigned to the view.
To have control over what model to bind to the view, you probably want to use a Controller Rendering, then you can pass in your own model from your controller.

How to get value dynamically added textbox values in MVC 3

I want to get the values of dynamically added Textbox on submit button in MVC 3.
I am storing the values in hidden field and getting using FromCollection. Is there any better approach?
If you name your values something like
MyValues[x] where x is a zero based, continuously increasing integer, you can receive the string values as a list of strings named MyValues.
This trick also works for properties if the main model object, if needed.
You should check some articles about how to bind to collections In ASP mvc, they could give you some ideas.
For example http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
You could do something like this (written very quickly outside of editor, so may have typos/issues):
Make a view model:
public class DynamicTextBoxViewModel
{
public IList<string> DynamicTextBox { get; set; }
public int OtherStuffInViewModel { get; set; }
}
Then in your Get Action:
var model = new YourViewModel
{
DynamicTextBoxList =
new List<DynamicTextBox>
{
new DynamicTextBox
{
TextBoxText = string.Empty,
}
},
OtherStuffInViewModel = xxx,
};
return View(model)
Then in your Post Action:
You would bind everything where you wanted it.
The idea is to move all the data into a ViewModel and pass that around so you gain the benefits of the ViewModel instead of passing around FormCollection - which is sloppier and more error prone.

MVC 3 Complicated validation of models

Current validation method for use in MVC 3 seems to be ValidationAttributes. I have a class validation that is very specific to that model and has interactions between a few properties.
Basically the model has a collection of other models and they are edited all in the same form. Let's call it ModelA and it has a collection of ModelB. One thing I might have to validate is that the sum of the some property of ModelB is less then a property of ModelA. The user has X number of points he can divide among some options.
ValidationAttributes are very generic and I'm not sure they are suited for this job.
I have no idea how IDateErrorInfo is supported in MVC 3 and whether it works straight out of the box.
One way would be to validate through a method but that means I can't do a clientside validation.
What is the proper way to do something like this? Are there any more options I have? Am I underestimating the power of ValidationAttribute?
IDateErrorInfo
IDateErrorInfo is supported by the MVC framework (a Microsoft tutorial can be found here). The default model binder will be reponsible for recreating model objects by binding the html form elements to the model. If the model binder detects that the model implements the interface then it will use the interface methods to validate each property in the model or to validate the model as a whole. See the tutorial for more information.
If you wanted to use client side validation using this method then (to quote Steve Sanderson) 'the most direct way to take advantage of additional validation rules is to manually generate the required attributes in the view':
<p>
#Html.TextBoxFor(m.ClientName, new { data_val = "true", data_val_email = "Enter a valid email address", data_val_required = "Please enter your name"})
#Html.ValidationMessageFor(m => m.ClientName)
</p>
This can then be used to trigger any client side validation that has been defined. See below for an example of how to define client side validation.
Explicit Validation
As you mentioned, you could explicity validate the model in the action. For example:
public ViewResult Register(MyModel theModel)
{
if (theModel.PropertyB < theModel.PropertyA)
ModelState.AddModelError("", "PropertyA must not be less then PropertyB");
if (ModelState.IsValid)
{
//save values
//go to next page
}
else
{
return View();
}
}
In the view you would then need to use #Html.ValidationSummary to display the error message as the above code would add a model level error and not a property level error.
To specify a property level error you can write:
ModelState.AddModelError("PropertyA", "PropertyA must not be less then PropertyB");
And then in the view use:
#Html.ValidationMessageFor(m => m.PropertyA);
to display the error message.
Again, any client side validation would need to be linked in by manually linking in the client side validation in the view by defining properties.
Custom Model Validation Attribute
If I understand the problem correctly, you are trying to validate a model which contains a single value and a collection where a property on the collection is to be summed.
For the example I will give, the view will present to the user a maximum value field and 5 value fields. The maximum value field will be a single value in the model where as the 5 value fields will be part of a collection. The validation will ensure that the sum of the value fields is not greater than the maximum value field. The validation will be defined as an attribute on the model which will also link in nicely to the javascript client side valdation.
The View:
#model MvcApplication1.Models.ValueModel
<h2>Person Ages</h2>
#using (#Html.BeginForm())
{
<p>Please enter the maximum total that will be allowed for all values</p>
#Html.EditorFor(m => m.MaximumTotalValueAllowed)
#Html.ValidationMessageFor(m => m.MaximumTotalValueAllowed)
int numberOfValues = 5;
<p>Please enter #numberOfValues different values.</p>
for (int i=0; i<numberOfValues; i++)
{
<p>#Html.EditorFor(m => m.Values[i])</p>
}
<input type="submit" value="submit"/>
}
I have not added any validation against the value fields as I do not want to overcomplicate the example.
The Model:
public class ValueModel
{
[Required(ErrorMessage="Please enter the maximum total value")]
[Numeric] //using DataAnnotationExtensions
[ValuesMustNotExceedTotal]
public string MaximumTotalValueAllowed { get; set; }
public List<string> Values { get; set; }
}
The Actions:
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(ValueModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
else
{
return RedirectToAction("complete"); //or whatever action you wish to define.
}
}
The Custom Attribute:
The [ValuesMustNotExceedTotal] attribute defined on the model can be defined by overriding the ValidationAttribute class:
public class ValuesMustNotExceedTotalAttribute : ValidationAttribute
{
private int maxTotalValueAllowed;
private int valueTotal;
public ValuesMustNotExceedTotalAttribute()
{
ErrorMessage = "The total of all values ({0}) is greater than the maximum value of {1}";
}
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, valueTotal, maxTotalValueAllowed);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
PropertyInfo maxTotalValueAllowedInfo = validationContext.ObjectType.GetProperty("MaximumTotalValueAllowed");
PropertyInfo valuesInfo = validationContext.ObjectType.GetProperty("Values");
if (maxTotalValueAllowedInfo == null || valuesInfo == null)
{
return new ValidationResult("MaximumTotalValueAllowed or Values is undefined in the model.");
}
var maxTotalValueAllowedPropertyValue = maxTotalValueAllowedInfo.GetValue(validationContext.ObjectInstance, null);
var valuesPropertyValue = valuesInfo.GetValue(validationContext.ObjectInstance, null);
if (maxTotalValueAllowedPropertyValue != null && valuesPropertyValue != null)
{
bool maxTotalValueParsed = Int32.TryParse(maxTotalValueAllowedPropertyValue.ToString(), out maxTotalValueAllowed);
int dummyValue;
valueTotal = ((List<string>)valuesPropertyValue).Sum(x => Int32.TryParse(x, out dummyValue) ? Int32.Parse(x) : 0);
if (maxTotalValueParsed && valueTotal > maxTotalValueAllowed)
{
return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
}
}
//if the maximum value is not supplied or could not be parsed then we still return that the validation was successful.
//why? because this attribute is only responsible for validating that the total of the values is less than the maximum.
//we use a [Required] attribute on the model to ensure that the field is required and a [Numeric] attribute
//on the model to ensure that the fields are input as numeric (supplying appropriate error messages for each).
return null;
}
}
Adding Client Side Validation to the Custom Attribute:
To add client side validation to this attribute it would need to implement the IClientValidatable interface:
public class ValuesMustNotExceedTotalAttribute : ValidationAttribute, IClientValidatable
{
//...code as above...
//this will be called when creating the form html to set the correct property values for the form elements
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule {
ValidationType = "valuesmustnotexceedtotal", //the name of the client side javascript validation (must be lowercase)
ErrorMessage = "The total of all values is greater than the maximum value." //I have provided an alternative error message as i'm not sure how you would alter the {0} and {1} in javascript.
};
yield return rule;
//note: if you set the validation type above to "required" or "email" then it would use the default javascript routines (by those names) to validate client side rather than the one we define
}
}
If you were to run the application at this point and view the source html for the field defining the attribute you will see the following:
<input class="text-box single-line" data-val="true" data-val-number="The MaximumTotalValueAllowed field is not a valid number." data-val-required="Please enter the maximum total value" data-val-valuesmustnotexceedtotal="The total of all values is greater than the maximum value." id="MaximumTotalValueAllowed" name="MaximumTotalValueAllowed" type="text" value="" />
In particular notice the validation attribute of data-val-valuesmustnotexceedtotal. This is how our client side validation will link to the validation attribute.
Adding Client Side Validation:
To add client side validation you need to add the following similar library references in the tag of the view:
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
You need to also ensure that the client side validation is switched on in the web.config although I think this should be on by default:
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
All that is left is to define the client side validation in the view. Note that the validation added here is defined in the view but if it was defined in a library then the custom attribute (maybe not this one) could be added to other models for other views:
<script type="text/javascript">
jQuery.validator.unobtrusive.adapters.add('valuesmustnotexceedtotal', [], function (options) {
options.rules['valuesmustnotexceedtotal'] = '';
options.messages['valuesmustnotexceedtotal'] = options.message;
});
//note: this will only be fired when the user leaves the maximum value field or when the user clicks the submit button.
//i'm not sure how you would trigger the validation to fire if the user leaves the value fields although i'm sure its possible.
jQuery.validator.addMethod('valuesmustnotexceedtotal', function (value, element, params) {
sumValues = 0;
//determine if any of the value fields are present and calculate the sum of the fields
for (i = 0; i <= 4; i++) {
fieldValue = parseInt($('#Values_' + i + '_').val());
if (!isNaN(fieldValue)) {
sumValues = sumValues + fieldValue;
valueFound = true;
}
}
maximumValue = parseInt(value);
//(if value has been supplied and is numeric) and (any of the fields are present and are numeric)
if (!isNaN(maximumValue) && valueFound) {
//perform validation
if (sumValues > maximumValue)
{
return false;
}
}
return true;
}, '');
</script>
And that should be it. I'm sure that there are improvements that can be made here and there and that if i've misunderstood the problem slightly that you should be able to tweak the validation for your needs. But I believe this validation seems to be the way that most developers code custom attributes including more complex client side validation.
Hope this helps. Let me know if you have any questions or suggestions regarding the above.
This is what you are looking for:
http://www.a2zdotnet.com/View.aspx?Id=182
I got some similar situation too, I need to compare the value of property A with property B, and I get it done by:
public sealed class PropertyAAttribute : ValidationAttribute
{
public string propertyBProperty { get; set; }
// Override the isValid function
public override bool IsValid(object value)
{
// Do your comparison here, eg:
return A >= B;
}
}
Then just use the custom validation attribute like this:
[PropertyA(propertyBProperty = "PropertyB")]
public string Property A {get; set;}
I also tried very hard and get this solution from others, Hope this help!
Your model class can implement the IValidatableObject interface.
This way you have access to all the properties of your model class and can perform all your custom validations.
You also have the IClientValidatable interface, for client side validations, but I'm not sure if by implementing it directly in the model class the client validations are picked by MVC since I only ever used this interface to specify client validations in custom validation attributes.

How to use CheckBox in View _CreateOrEdit.cshtml for an integer or character database field

MVC 3, EntityFramework 4.1, Database First, Razor customization:
I have an old database that sometimes uses Int16 or Char types for a field that must appear as a CheckBox in the MVC _CreateOrEdit.cshtml View. If it is an Int, 1=true and 0=false. If it is a Char, "Y"=true and "N"=false. This is too much for the Entity Framework to convert automatically. For the Details View, I can use:
#Html.CheckBox("SampleChkInt", Model.SampleChkInt==1?true:false)
But this won't work in place of EditorFor in the _CreateOrEdit.cshtml View.
How to do this? I was thinking of a custom HtmlHelper, but the examples I've found don't show me how to tell EntityFramework to update the database properly. There are still other such customizations that I might like to do, where the MVC View does not match the database cleanly enough for EntityFramework to do an update. Answering this question would be a good example. I am working on a sample project, using the following automatically generated (so I can't make changes to it) model class:
namespace AaWeb.Models
{
using System;
using System.Collections.Generic;
public partial class Sample
{
public int SampleId { get; set; }
public Nullable<bool> SampleChkBit { get; set; }
public Nullable<short> SampleChkInt { get; set; }
public Nullable<System.DateTime> SampleDate { get; set; }
public string SampleHtml { get; set; }
public Nullable<int> SampleInt { get; set; }
public Nullable<short> SampleYesNo { get; set; }
public string Title { get; set; }
public byte[] ConcurrencyToken { get; set; }
}
}
I figured it out. Do not need a model binder or Html Helper extension:
In _CreateOrEdit.cshtml, I made up a new name SampleChkIntBool for the checkbox, and set it according to the value of the model SampleChkInt:
#Html.CheckBox("SampleChkIntBool", Model == null ? false : ( Model.SampleChkInt == 1 ? true : false ), new { #value = "true" })
Then, in the [HttpPost] Create and Edit methods of the Sample.Controller, I use Request["SampleChkIntBool"] to get the value of SampleChkIntBool and use it to set the model SampleChkInt before saving:
string value = Request["SampleChkIntBool"];
// #Html.CheckBox always generates a hidden field of same name and value false after checkbox,
// so that something is always returned, even if the checkbox is not checked.
// Because of this, the returned string is "true,false" if checked, and I only look at the first value.
if (value.Substring(0, 4) == "true") { sample.SampleChkInt = 1; } else { sample.SampleChkInt = 0; }
I believe a custom model binder would be in order here to handle the various mappings to your model.
ASP.NET MVC Model Binder for Generic Type
etc
etc
Here is the way to go from checkbox to database, without the special code in the controller:
// The following statement added to the Application_Start method of Global.asax.cs is what makes this class apply to a specific entity:
// ModelBinders.Binders.Add(typeof(AaWeb.Models.Sample), new AaWeb.Models.SampleBinder());
// There are two ways to do this, choose one:
// 1. Declare a class that extends IModelBinder, and supply all values of the entity (a big bother).
// 2. Declare a class extending DefaultModelBinder, and check for and supply only the exceptions (much better).
// This must supply all values of the entity:
//public class SampleBinder : IModelBinder
//{
// public object BindModel(ControllerContext cc, ModelBindingContext mbc)
// {
// Sample samp = new Sample();
// samp.SampleId = System.Convert.ToInt32(cc.HttpContext.Request.Form["SampleId"]);
// // Continue to specify all of the rest of the values of the Sample entity from the form, as done in the above statement.
// // ...
// return samp;
// }
//}
// This must check the property names and supply appropriate values from the FormCollection.
// The base.BindProperty must be executed at the end, to make sure everything not specified is take care of.
public class SampleBinder : DefaultModelBinder
{
protected override void BindProperty( ControllerContext cc, ModelBindingContext mbc, System.ComponentModel.PropertyDescriptor pd)
{
if (pd.Name == "SampleChkInt")
{
// This converts the "true" or "false" of a checkbox to an integer 1 or 0 for the database.
pd.SetValue(mbc.Model, (Nullable<Int16>)(cc.HttpContext.Request.Form["SampleChkIntBool"].Substring(0, 4) == "true" ? 1 : 0));
// To do the same in the reverse direction, from database to view, use pd.GetValue(Sample object).
return;
}
// Need the following to get all of the values not specified in this BindProperty method:
base.BindProperty(cc, mbc, pd);
}
}

Resources