How to call ValidationAttributes manually? (DataAnnotations and ModelState) - asp.net

We have a need within some of our logic to iterate through the properties of a model to auto-bind properties and want to extend the functionality to include the new dataannotations in C# 4.0.
At the moment, I basically iterate over each property loading in all ValidationAttribute instances and attempting to validate using the Validate/IsValid function, but this doesn't seem to be working for me.
As an example I have a model such as:
public class HobbyModel
{
[Required(AllowEmptyStrings = false, ErrorMessage = "Do not allow empty strings")]
[DisplayName("Hobby")]
[DataType(DataType.Text)]
public string Hobby
{
get;
set;
}
}
And the code to check the attributes is:
object[] attributes = propertyInfo.GetCustomAttributes(true);
TypeConverter typeConverter =
TypeDescriptor.GetConverter(typeof(ValidationAttribute));
bool isValid = false;
foreach (object attr in attributes)
{
ValidationAttribute attrib = attr as ValidationAttribute;
if (attrib != null)
{
attrib.Validate(obj, propertyInfo.Name);
}
}
I've debugged the code and the model does have 3 attributes, 2 of which are derived from ValidationAttribute, but when the code passes through the Validate function (with a empty or null value) it does thrown an exception as expected.
I'm expecting I'm doing something silly, so am wondering whether anyone has used this functionality and could help.
Thanks in advance,
Jamie

This is because you are passing the source object to the Validate method, instead of the property value. The following is more likely to work as expected (though obviously not for indexed properties):
attrib.Validate(propertyInfo.GetValue(obj, null), propertyInfo.Name);
You would certainly have an easier time using the Validator class as Steven suggested, though.

You do use the System.ComponentModel.DataAnnotations.Validator class to validate objects.

Related

ASP.NET setting and getting viewstate in a property

can someone please explain me the code written below
public IList<GetProductPrice> CurrentPage
{
get { return ViewState["CurrentPage"] as List<GetProductPrice>; }
set { ViewState["CurrentPage"] = value; }
}
It is called a Property. They generate a getter and setter functions when compiled:
List<GetProductPrice> GetCurrentPage(){
return ViewState["CurrentPage"] as List<GetProductPrice>;
}
void SetCurrentPage(List<GetProductPrice> value) {
ViewState["CurrentPage"] = value;
}
//i think its actual get_.. but it doesn't matter for the example
So its generates ease of use getter setters. which you can just call by using:
var test = CurrentPage; //compiled to var test = GetCurrenctPage();
CurrentPage = test; //compiled to SetCurrentPage(test);
If you leave the getter and setter empty like this:
public int CurrentPage
{
get;
set;
}
it will also generate a backing field on the class where it stores the data:
private int _currentPage;
public GetCurrentPage(){ return _currentPage }
public SetCurrentPage(int value) { _currentPage = value }
Why do we do this?
Using getters and setters is a very old best practise from java (where ide's would have an option to generate them). But this would lead to a lot of boilerplate code!
In C# they try to counter this by adding these properties. But why do we need getters and setters? For example if you want to be notified when a value changes (to mark the classes it self as dirty). I think entity framework uses it to track if a model is changed otherwise it wont do a db update call. There are also other usefull tools that inject code in properties on compile time. to add extra functionality.
How not to use it:
using properties to return HttpContext.Current Is a dangerous one because you secretly depend on the HttpContext so try not to do this at any time!
Generally its also bad practise to use it when the code inside the get or set is very heavy (very instensive). Its bad practise because someone else using the code might think he is just setting a property/field while actually some very heavy code is executed. its best practice to make a special function for this instead and private the getter/setter:
public int Property {get; private set; }
public SetProperty(int value){
//intensive code here:
Property = value;
}
This property is letting the consumer of the property to use it like Local collection without referring the ViewState in the code. It will make the code simple and easy to use.
get { return ViewState["CurrentPage"] as List<GetProductPrice>; }
Here the ViewState object ViewState["CurrentPage"] is converted to list of GetProductPrice
set { ViewState["CurrentPage"] = value; }
Here the List is assigned to ViewState["CurrentPage"]
This code will only work in a controller, where ViewState is a property. This CurrentPage property provides a statically-typed way to access a certain ViewState item through that property.
So instead of sprinkling ViewState["CurrentPage"] as List<GetProductPrice> all over your controller code where you want to access the "current page", you can now simply use the CurrentPage property.
Of course "current page" is a term made up by the developer who chose to name things like this, I don't see how a List<GetProductPrice> has a relation to the "current page".

How ViewBag in ASP.NET MVC works

How does the ASP.NET MVC's ViewBag work? MSDN says it is just an Object, which intrigues me, how does "Magic" properties such as ViewBag.Foo and magic strings ViewBag["Hello"] actually work?
Also, how can I make one and use it in my ASP.NET WebForms app?
Examples would be really appreciated!
ViewBag is of type dynamic but, is internally an System.Dynamic.ExpandoObject()
It is declared like this:
dynamic ViewBag = new System.Dynamic.ExpandoObject();
which is why you can do :
ViewBag.Foo = "Bar";
A Sample Expander Object Code:
public class ExpanderObject : DynamicObject, IDynamicMetaObjectProvider
{
public Dictionary<string, object> objectDictionary;
public ExpanderObject()
{
objectDictionary = new Dictionary<string, object>();
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
object val;
if (objectDictionary.TryGetValue(binder.Name, out val))
{
result = val;
return true;
}
result = null;
return false;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
try
{
objectDictionary[binder.Name] = value;
return true;
}
catch (Exception ex)
{
return false;
}
}
}
It's a dynamic object, meaning you can add properties to it in the controller, and read them later in the view, because you are essentially creating the object as you do, a feature of the dynamic type. See this MSDN article on dynamics. See this article on it's usage in relation to MVC.
If you wanted to use this for web forms, add a dynamic property to a base page class like so:
public class BasePage : Page
{
public dynamic ViewBagProperty
{
get;
set;
}
}
Have all of your pages inherit from this. You should be able to, in your ASP.NET markup, do:
<%= ViewBagProperty.X %>
That should work. If not, there are ways to work around it.
The ViewBag is an System.Dynamic.ExpandoObject as suggested. The properties in the ViewBag are essentially KeyValue pairs, where you access the value by the key. In this sense these are equivalent:
ViewBag.Foo = "Bar";
ViewBag["Foo"] = "Bar";
ViewBag is used to pass data from Controller Action to view to render the data that being passed. Now you can pass data using between Controller Action and View either by using ViewBag or ViewData.
ViewBag: It is type of Dynamic object, that means you can add new fields to viewbag dynamically and access these fields in the View. You need to initialize the object of viewbag at the time of creating new fields.
e.g:
1. Creating ViewBag:
ViewBag.FirstName="John";
Accessing View:
#ViewBag.FirstName.
ViewBag is of type dynamic. More, you cannot do ViewBag["Foo"]. You will get exception - Cannot apply indexing with [] to an expression of type 'System.Dynamic.DynamicObject'.
Internal implementation of ViewBag actually stores Foo into ViewData["Foo"] (type of ViewDataDictionary), so those 2 are interchangeable. ViewData["Foo"] and ViewBag.Foo.
And scope. ViewBag and ViewData are ment to pass data between Controller's Actions and View it renders.
ViewBag is a dynamic type that allow you to dynamically set or get values and allow you to add any number of additional fields without a strongly-typed class
They allow you to pass data from controller to view.
In controller......
public ActionResult Index()
{
ViewBag.victor = "My name is Victor";
return View();
}
In view
#foreach(string a in ViewBag.victor)
{
.........
}
What I have learnt is that both should have the save dynamic name property ie ViewBag.victor
public dynamic ViewBag
{
get
{
if (_viewBag == null)
{
_viewBag = new DynamicViewData(() => ViewData);
}
return _viewBag;
}
}

IValidatableObject Validate method firing when DataAnnotations fails

I've a ViewModel which has some DataAnnotations validations and then for more complex validations implements IValidatableObject and uses Validate method.
The behavior I was expecting was this one: first all the DataAnnotations and then, only if there were no errors, the Validate method. How ever I find out that this isn't always true. My ViewModel (a demo one) has three fileds one string, one decimal and one decimal?. All the three properties have only Required attribute. For the string and the decimal? the behavior is the expected one, but for the decimal, when empty, Required validation fails (so far so good) and then executes the Validate method. If I inspect the property its value is zero.
What is going on here? What am I missing?
Note: I know that Required attribute is suppose to check if the value is null. So I'd expect to be told not to use Required attribute in not-nullable types (because it wont ever trigger), or, that somehow the attribute understand the POST values and note that the field wasn't filled. In the first case the attribute shouldn't trigger and the Validate method should fire. In the second case the attribute should trigger and the Validate method shouldn't fire. But my result are: the attributes triggers and the Validate method fires.
Here is the code (nothing too special):
Controller:
public ActionResult Index()
{
return View(HomeModel.LoadHome());
}
[HttpPost]
public ActionResult Index(HomeViewModel viewModel)
{
try
{
if (ModelState.IsValid)
{
HomeModel.ProcessHome(viewModel);
return RedirectToAction("Index", "Result");
}
}
catch (ApplicationException ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, "Internal error.");
}
return View(viewModel);
}
Model:
public static HomeViewModel LoadHome()
{
HomeViewModel viewModel = new HomeViewModel();
viewModel.String = string.Empty;
return viewModel;
}
public static void ProcessHome(HomeViewModel viewModel)
{
// Not relevant code
}
ViewModel:
public class HomeViewModel : IValidatableObject
{
[Required(ErrorMessage = "Required {0}")]
[Display(Name = "string")]
public string String { get; set; }
[Required(ErrorMessage = "Required {0}")]
[Display(Name = "decimal")]
public decimal Decimal { get; set; }
[Required(ErrorMessage = "Required {0}")]
[Display(Name = "decimal?")]
public decimal? DecimalNullable { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
yield return new ValidationResult("Error from Validate method");
}
}
View:
#model MVCTest1.ViewModels.HomeViewModel
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm(null, null, FormMethod.Post))
{
<div>
#Html.ValidationSummary()
</div>
<label id="lblNombre" for="Nombre">Nombre:</label>
#Html.TextBoxFor(m => m.Nombre)
<label id="lblDecimal" for="Decimal">Decimal:</label>
#Html.TextBoxFor(m => m.Decimal)
<label id="lblDecimalNullable" for="DecimalNullable">Decimal?:</label>
#Html.TextBoxFor(m => m.DecimalNullable)
<button type="submit" id="aceptar">Aceptar</button>
<button type="submit" id="superAceptar">SuperAceptar</button>
#Html.HiddenFor(m => m.Accion)
}
Considerations after comments' exchange:
The consensual and expected behavior among developers is that IValidatableObject's method Validate() is only called if no validation attributes are triggered. In short, the expected algorithm is this (taken from the previous link):
Validate property-level attributes
If any validators are invalid, abort validation returning the failure(s)
Validate the object-level attributes
If any validators are invalid, abort validation returning the failure(s)
If on the desktop framework and the object implements IValidatableObject, then call its Validate method and return any failure(s)
However, using question's code, Validate is called even after [Required] triggers. This seems an obvious MVC bug. Which is reported here.
Three possible workarounds:
There's a workaround here although with some stated problems with it's usage, apart from breaking the MVC expected behavior. With a few changes to avoid showing more than one error for the same field here is the code:
viewModel
.Validate(new ValidationContext(viewModel, null, null))
.ToList()
.ForEach(e => e.MemberNames.ToList().ForEach(m =>
{
if (ModelState[m].Errors.Count == 0)
ModelState.AddModelError(m, e.ErrorMessage);
}));
Forget IValidatableObject and use only attributes. It's clean, direct, better to handle localization and best of all its reusable among all models. Just implement ValidationAttribute for each validation you want to do. You can validate the all model or particular properties, that's up to you. Apart from the attributes available by default (DataType, Regex, Required and all that stuff) there are several libraries with the most used validations. One which implements the "missing ones" is FluentValidation.
Implement only IValidatableObject interface throwing away data annotations. This seems a reasonable option if it's a very particular model and it doesn't requires much validation. On most cases the developer will be doing all that regular and common validation (i.e. Required, etc.) which leads to code duplication on validations already implemented by default if attributes were used. There's also no re-usability.
Answer before comments:
First of all I've created a new project, from scratch with only the code you provided. It NEVER triggered both data annotations and Validate method at the same time.
Anyway, know this,
By design, MVC3 adds a [Required]attribute to non-nullable value types, like int, DateTime or, yes, decimal. So, even if you remove required attribute from that decimal it works just like it is one there.
This is debatable for its wrongness (or not) but its the way it's designed.
In you example:
'DataAnnotation' triggers if [Required] is present and no value is given. Totally understandable from my point of view
'DataAnnotation' triggers if no [Required] is present but value is non-nullable. Debatable but I tend to agree with it because if the property is non-nullable, a value must be inputted, otherwise don't show it to the user or just use a nullable decimal.
This behavior, as it seems, may be turned off with this within your Application_Start method:
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
I guess the property's name is self-explanatory.
Anyway, I don't understand why do you want to the user to input something not required and don't make that property nullable. If it's null then it is your job to check for it, if you don't wan't it to be null, before validation, within the controller.
public ActionResult Index(HomeViewModel viewModel)
{
// Complete values that the user may have
// not filled (all not-required / nullables)
if (viewModel.Decimal == null)
{
viewModel.Decimal = 0m;
}
// Now I can validate the model
if (ModelState.IsValid)
{
HomeModel.ProcessHome(viewModel);
return RedirectToAction("Ok");
}
}
What do you think it's wrong on this approach or shouldn't be this way?

NVelocity extension method ASP.NET webform

I was wondering if it's possible to use an extension method with asp.net webforms and nvelocity. I would like to set some defaults if the string value is null or empty.
Example of .vm file:
Example of my email body...
Billable Status: $billableStatus.Evaluate()
rest of my email body...
Attempted extension method:
public static class Helper
{
public static string Evaluate(this string value)
{
if (String.IsNullOrEmpty(value))
return "Not Provided";
else
return value;
}
}
Or is there an alternative to what I'm tryting to accomplish?
I don't think NVelocity can resolve extension methods with C#/VB.NET syntax sugar. What I do is register an instance of a helper in the velocity context:
var context = VelocityContext();
context.Put("helper", new Helper());
context.Put("billableStatus", "something");
...
and then in your template:
$helper.Evaluate($billableStatus)
You have to make your helper non-static for this to work, of course.
I came across something similar in past and I was looking for something more sophisticated and with more control. I found that NVelocity does provide a way to intercept the method and property calls but for that you will have to implement certain things. In order to make your custom interceptor you will need to implement NVelocity.IDuck. For example
public class MyClass : NVelocity.IDuck
{
public object GetInvoke(string propName)
{
....
}
public object Invoke(string method, params object[] args)
{
....
}
public void SetInvoke(string propName, object value)
{
....
}
}
Now any instance of MyClass will intercept and pass the method and property calls to our these three function implementation and give us a chance to resolve and return the output. You may notice from these three function signatures that in order to implement them we may need some reflection where we can locate respective methods on available extension types and execute them. If needed you can read following blog post for more details about going this way. NVelocity and extension methods

ASP.NET MVC - Posting a form with custom fields of different data types

In my ASP.NET MVC 2 web application, I allow users to create custom input fields of different data types to extend our basic input form. While tricky, building the input form from a collection of custom fields is straight-forward enough.
However, I'm now to the point where I want to handle the posting of this form and I'm not certain what the best way to handle this would be. Normally, we'd use strongly-typed input models that get bound from the various statically-typed inputs available on the form. However, I'm at a loss for how to do this with a variable number of input fields that represent different data types.
A representative input form might look something like:
My date field: [ date time input
control ]
My text field: [ text input
field ]
My file field: [ file upload
control ]
My number field: [ numerical input control ]
My text field 2: [text input field ]
etc...
Ideas I've thought about are:
Sending everything as strings (except for the file inputs, which would need to be handled specially).
Using a model with an "object" property and attempting to bind to that (if this is even possible).
Sending a json request to my controller with the data encoded properly and attempting to parse that.
Manually processing the form collection in my controller post action - certainly an option, but I'd love to avoid this.
Has anyone tackled an issue like this before? If so, how did you solve it?
Update:
My "base" form is handled on another input area all together, so a solution doesn't need to account for any sort of inheritence magic for this. I'm just interested in handling the custom fields on this interface, not my "base" ones.
Update 2:
Thank you to ARM and smartcaveman; both of you provided good guidance for how this could be done. I will update this question with my final solution once its been implemented.
This is how I would begin to approach the issue. A custom model binder would be pretty easy to build based on the FormKey property (which could be determined by the index and/or label, depending).
public class CustomFormModel
{
public string FormId { get; set; }
public string Label { get; set; }
public CustomFieldModel[] Fields { get; set; }
}
public class CustomFieldModel
{
public DataType DateType { get; set; } // System.ComponentModel.DataAnnotations
public string FormKey { get; set; }
public string Label { get; set; }
public object Value { get; set; }
}
public class CustomFieldModel<T> : CustomFieldModel
{
public new T Value { get; set; }
}
Also, I noticed one of the comments below had a filtered model binder system. Jimmy Bogard from Automapper made a really helpful post about this method at http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/03/17/a-better-model-binder.aspx , and later revised in, http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/11/19/a-better-model-binder-addendum.aspx . It has been very helpful for me in building custom model binders.
Update
I realized that I misinterpreted the question, and that he was specifically asking how to handle posting of the form "with a variable number of input fields that represent different data types". I think the best way to do this is to use a structure similar to above but leverage the Composite Pattern. Basically, you will need to create an interface like IFormComponent and implement it for each datatype that would be represented. I wrote and commented an example interface to help explain how this would be accomplished:
public interface IFormComponent
{
// the id on the html form field. In the case of a composite Id, that doesn't have a corresponding
// field you should still use something consistent, since it will be helpful for model binding
// (For example, a CompositeDateField appearing as the third field in the form should have an id
// something like "frmId_3_date" and its child fields would be "frmId_3_date_day", "frmId_3_date_month",
// and "frmId_3_date_year".
string FieldId { get; }
// the human readable field label
string Label { get; }
// some functionality may require knowledge of the
// Parent component. For example, a DayField with a value of "30"
// would need to ask its Parent, a CompositeDateField
// for its MonthField's value in order to validate
// that the month is not "February"
IFormComponent Parent { get; }
// Gets any child components or null if the
// component is a leaf component (has no children).
IList<IFormComponent> GetChildren();
// For leaf components, this method should accept the AttemptedValue from the value provider
// during Model Binding, and create the appropriate value.
// For composites, the input should be delimited in someway, and this method should parse the
// string to create the child components.
void BindTo(string value);
// This method should parse the Children or Underlying value to the
// default used by your business models. (e.g. a CompositeDateField would
// return a DateTime. You can get type safety by creating a FormComponent<TValue>
// which would help to avoid issues in binding.
object GetValue();
// This method would render the field to the http response stream.
// This makes it easy to render the forms simply by looping through
// the array. Implementations could extend this for using an injected
// formatting
void Render(TextWriter writer);
}
I am assuming that the custom forms can be accessed via some sort of id which can be contained as a form parameter. With that assumption, the model binder and provider could look something like this.
public interface IForm : IFormComponent
{
Guid FormId { get; }
void Add(IFormComponent component);
}
public interface IFormRepository
{
IForm GetForm(Guid id);
}
public class CustomFormModelBinder : IModelBinder
{
private readonly IFormRepository _repository;
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult result;
if(bindingContext.ValueProvider.TryGetValue("_customFormId", out result))
{
var form = _repository.GetForm(new Guid(result.AttemptedValue));
var fields = form.GetChildren();
// loop through the fields and bind their values
return form;
}
throw new Exception("Form ID not found.");
}
}
Obviously, all the code here is just to get the point across, and would need to be completed and cleaned up for actual use. Also, even if completed this would only bind to an implementation of the IForm interface, not a strongly typed business object. (It wouldn't be a huge step to convert it to a dictionary and build a strongly typed proxy using the Castle DictionaryAdapter, but since your users are dynamically creating the forms on the site, there is probably no strongly typed model in your solution and this is irrelevant). Hope this helps more.
Take a peek at what I did here: MVC2 Action to handle multiple models and see if can get you on the right track.
If you use a FormCollection as one of your parameters to your action, you can then go thru that form collection looking for bits of data here or there in order to bind those values to whatever an then save the data. You are most likely going to need to take advantage of both strategy and command patterns to get this to work.
Best of luck, feel free to ask follow-up questions.
Edit:
Your method which does the work should look something like this:
private/public void SaveCustomFields(var formId, FormCollection collection) //var as I don't know what type you are using to Id the form.
{
var binders = this.binders.select(b => b.CanHandle(collection)); //I used IOC to get my list of IBinder objects
// Method 1:
binders.ForEach(b => b.Save(formId, collection)); //This is the execution implementation.
// Method 2:
var commands = binders.Select(b => b.Command(formId, collection));
commands.ForEach(c => c.Execute());
}
public DateBinder : IBinder //Example binder
{
public bool CanHandle(FormCollection collection)
{
return (null != collection["MyDateField"]); //Whatever the name of this field is.
}
//Method 1
public void Save(var formId, FormCollection collection)
{
var value = DateTime.Parse(collection["MyDateField"]);
this.someLogic.Save(formId, value); //Save the value with the formId, or however you wish to save it.
}
//Method 2
public Command Command(var formId, FormCollection collection)
{
//I haven't done command pattern before so I'm not sure exactly what to do here.
//Sorry that I can't help further than that.
}
}
I would think one of the best options is to create a custom model binder, which makes it possible to have custom logic behind the scenes and still very customizable code behind.
Maybe these articles can help you:
http://www.gregshackles.com/2010/03/templated-helpers-and-custom-model-binders-in-asp-net-mvc-2/
http://www.singingeels.com/Articles/Model_Binders_in_ASPNET_MVC.aspx
More specifically I would probably take as the controller argument a custom class with all "base" properties included. The class could then for example include a dictionary linking the name of each field to either just an object or an interface which you implement once for each data-type making it simple to process the data later.
/Victor

Resources