internal HtmlTag PreProcess(HtmlTag tag, WFModelMetaData metadata, TagTypes tagType, string markupName, string reflectName, object model) { foreach (IHtmlTagPreProcessor processor in _PreProcessors) { tag = processor.PreRenderProcess(tag, ref metadata, tagType, markupName, reflectName, model); } return(tag); }
private void Initialize(TModel model, WFModelMetaData metadata) { _Model = model; _MetaData = metadata; _PreProcessors.Add(new WFValidationPreProcessor()); _PreProcessors.Add(new WFHTMLEncodePreProcessor()); }
internal HtmlTag PreProcess(HtmlTag tag, WFModelMetaData metadata, TagTypes tagType, string propertyName, PropertyInfo expBody, object model) { foreach (IHtmlTagPreProcessor processor in _PreProcessors) { tag = processor.PreRenderProcess(tag, ref metadata, tagType, propertyName, expBody, model); } return(tag); }
/// <summary> /// !! MUST be run at the end of the form in markup. !! /// Outputs a script tag containing JavaScript code to enable validation on client side. /// </summary> /// <returns></returns> public static string EnableClientValidation(WFModelMetaData WFMetaData, string formId) { return ((new HtmlTag("script", new { type = "text/javascript", language = "javascript" }) { InnerText = WFScriptGenerator.EnableClientValidationScript(WFMetaData, formId) }.Render()) + WFScriptGenerator.SetupClientValidationScriptHtmlTag().Render()); }
private static HtmlTag GetTagFromExpression <TProperty>(TagTypes tagType, Expression <Func <TModel, TProperty> > expression, TModel model, WFModelMetaData metadata, object htmlProperties, HtmlHelper <TModel> htmlHelper) { return(GetTagFromExpression <TProperty>(tagType, expression, model, metadata, htmlProperties, htmlHelper, null, "", false, false)); }
/// <summary> /// Validate the model against form values (not against itself). /// </summary> /// <typeparam name="TModel">The type of the model tied to this page</typeparam> /// <param name="metadata">The metadata object which stores validation information. This usually lives on the Html object.</param> /// <param name="model">The model being validated.</param> /// <param name="context">The HTTP context where form values are stored to validate. This is usually HttpContext.Current.</param> /// <param name="prefix">The prefix to separate different objects in form data.<br/> /// ie: object1_FirstName=John, object2_FirstName=Joe</param> /// <returns>Returns 'true' if the values in the form data validate successfully.</returns> public static bool TryValidateModel <TModel>(WFModelMetaData metadata, TModel model, HttpContext context, string prefix) { return(WFUtilities.TryValidateModel(model, prefix, new WFHttpContextValueProvider(context), metadata, new WFTypeRuleProvider(model))); }
public static string EnableClientValidation(WFModelMetaData WFMetaData) { return(EnableClientValidation(WFMetaData, "")); }
public HtmlHelper(Control pageControl, TModel model, WFModelMetaData metadata) { Initialize(model, metadata); }
/// <summary> /// Root TryValidateModel() method. Returns false if any validation errors are found. /// </summary> /// <param name="model">A pointer to the current model object</param> /// <param name="prefix">Optional. A prefix to search and filter values from the value provider.</param> /// <param name="values">A class implementing IWFValueProvider (examples include WFObjectValueProvider and WFHttpContextValueProvider)</param> /// <param name="metadata">Optional. Required to collect error data or show error markup on a page. The current WFModelMetaData object.</param> /// <param name="ruleProvider">A class implementing IWFRuleProvider (examples include WFTypeRuleProvider and WFXmlRuleSetRuleProvider).<br/> /// This object provides the rules (ie: DataAnnotations) that needed to be validated, and which properties to validate them against.<br/> /// All other properties are ignored.</param> /// <returns>Returns false if any validation errors were found.</returns> public static bool TryValidateModel(object model, string prefix, IWFValueProvider values, WFModelMetaData metadata, IWFRuleProvider ruleProvider) { bool validated = true; //Make sure we have metadata metadata = metadata == null ? metadata = new WFModelMetaData() : metadata; metadata.Errors = new List <string>(); //Create a rule provider if one was not provided. WFTypeRuleProvider will handle [MetadataType] ruleProvider = ruleProvider == null ? new WFTypeRuleProvider(model) : ruleProvider; validated = validateModelAttributes(model, ruleProvider.GetClassValidationAttributes(), metadata.Errors, ruleProvider.ModelDisplayName); if (metadata.Errors.Count > 0) { validated = false; } foreach (PropertyInfo pi in ruleProvider.GetProperties()) { if (values.ContainsKey(prefix + pi.Name)) { WFModelMetaProperty metaprop = null; foreach (ValidationAttribute attr in ruleProvider.GetPropertyValidationAttributes(pi.Name)) { if (attr as IWFRequireValueProviderContext != null) { ((IWFRequireValueProviderContext)attr).SetValueProvider(values); } string displayName = ruleProvider.GetDisplayNameForProperty(pi.Name); bool isValid = false; if (attr.GetType() == typeof(RangeAttribute)) { try { isValid = attr.IsValid(values.KeyValue(prefix + pi.Name)); } catch (Exception ex) { if (ex.GetType() == typeof(FormatException)) { isValid = false; } else { throw ex; } } } else { isValid = attr.IsValid(values.KeyValue(prefix + pi.Name)); } if (!isValid) { validated = false; metadata.Errors.Add(attr.FormatErrorMessage(displayName)); if (metaprop == null) // Try to find it ... { foreach (WFModelMetaProperty mx in metadata.Properties) { if (mx.ModelObject == model && pi.Name.ToLower() == mx.PropertyName.ToLower()) { metaprop = mx; break; } } } if (metaprop == null) // Make a new one ... { metaprop = new WFModelMetaProperty(); metaprop.ModelObject = model; metaprop.PropertyName = pi.Name; metaprop.DisplayName = displayName; metaprop.MarkupName = prefix + pi.Name; metaprop.ValidationAttributes.Add(attr); metadata.Properties.Add(metaprop); } metaprop.HasError = true; metaprop.Errors.Add(attr.FormatErrorMessage(displayName)); } } } } return(validated); }
/// <summary> /// Render a Control (.aspx, .ascx) and return it as a string, setting the Model property to Model /// Use discretion when specifying the pageInstance, as some server controls will throw an error when WFPageHolder is not used. /// !! You should not pass the current page as the pageInstance !! This method assumes you know what you're doing. /// </summary> /// <param name="path">The physical path of the ascx/aspx file.</param> /// <param name="Model">The Model that will be used and applied to the public 'Model' property of the UserControl/Page.</param> /// <param name="pageInstance">pageInstance is optional and can be null.</param> /// <param name="ViewBag">If a public property 'ViewBag' exists on the target control/page, it will be set to this object.</param> /// <param name="MetaData">A MetaData object that can be shared among all views rendered for this request.</param> /// <returns></returns> public static string RenderControl(string path, object Model, System.Web.UI.Page pageInstance, object ViewBag, WFModelMetaData MetaData) { Page wph = pageInstance == null ? new WFPageHolder() as Page : pageInstance; Control ctrl = wph.LoadControl(path); if (ctrl == null) { return(""); } PropertyInfo pi = ctrl.GetType().GetProperties().FirstOrDefault(p => p.Name == "Model"); if (pi == null && Model != null) { throw new Exception("Did not find the 'Model' property on the target page/control to render. Make sure 'Model' is a public property with a 'setter'"); } else if (pi != null && Model != null) { try { pi.SetValue(ctrl, Model, null); } catch (Exception ex) { throw new Exception("Error assigning the source Model to the destination Model property when Rendering a control. Source type [" + Model.GetType().Name + "] and Destination type [" + pi.PropertyType.Name + "]. The inner exception may have more information.", ex); } } PropertyInfo piViewBag = ctrl.GetType().GetProperties().FirstOrDefault(p => p.Name == "ViewBag"); if (piViewBag != null) { piViewBag.SetValue(ctrl, ViewBag, null); } PropertyInfo piHTML = ctrl.GetType().GetProperties().FirstOrDefault(p => p.Name == "Html"); if (piHTML != null) { object helper = piHTML.GetValue(ctrl, null); if (helper != null) { //Share MetaData with this partial view helper.GetType().GetProperty("MetaData") .SetValue(helper, MetaData, null); } } wph.Controls.Add(ctrl); StringWriter output = new StringWriter(); HttpContext.Current.Server.Execute(wph, output, false); return(output.ToString()); }
/// <summary> /// Render a Control (.aspx, .ascx) and return it as a string, setting the Model property to Model /// Use discretion when specifying the pageInstance, as some server controls will throw an error when WFPageHolder is not used. /// !! You should not pass the current page as the pageInstance !! This method assumes you know what you're doing. /// </summary> /// <param name="path">The physical path of the ascx/aspx file.</param> /// <param name="Model">The Model that will be used and applied to the public 'Model' property of the UserControl/Page.</param> /// <param name="pageInstance">pageInstance is optional and can be null.</param> /// <param name="ViewBag">If a public property 'ViewBag' exists on the target control/page, it will be set to this object.</param> /// <param name="MetaData">A MetaData object that can be shared among all views rendered for this request.</param> /// <returns></returns> public static string RenderControl(string path, object Model, WFModelMetaData MetaData) { return(RenderControl(path, Model, null, null, MetaData)); }
private static HtmlTag GetTagFromExpression <TProperty>(TagTypes tagType, Expression <Func <TModel, TProperty> > expression, TModel model, WFModelMetaData metadata, object htmlProperties, HtmlHelper <TModel> htmlHelper, IEnumerable <SelectListItem> selectList, string optionLabel, bool useLabel, bool isChecked) { ModelMetaData mmd = ModelMetaData.FromLambdaExpression(expression, model); string reflectName = mmd.PropertyName; string markupName = mmd.PropertyName; HtmlTag tag = null; if (tagType == TagTypes.InputBox) { tag = new HtmlTag("input", true); tag.Attr("name", mmd.PropertyName); tag.Attr("id", mmd.PropertyName); tag.Attr("type", "text"); tag.Attr("value", GetHTMLValue(mmd.ModelAccessor())); } else if (tagType == TagTypes.Checkbox) { tag = new HtmlTag("input", true); tag.Attr("name", mmd.PropertyName); tag.Attr("id", mmd.PropertyName); tag.Attr("type", "checkbox"); if (GetHTMLValueAsBoolean(mmd.ModelAccessor())) { tag.Attr("checked", "checked"); } } else if (tagType == TagTypes.Hidden) { tag = new HtmlTag("input", true); tag.Attr("type", "hidden"); tag.Attr("value", GetHTMLValue(mmd.ModelAccessor())); tag.Attr("name", mmd.PropertyName); tag.Attr("id", mmd.PropertyName); } else if (tagType == TagTypes.Label) { tag = new HtmlTag("label"); tag.Attr("For", mmd.PropertyName); PropertyInfo pi = (PropertyInfo)((MemberExpression)expression.Body).Member; DisplayNameAttribute datt = pi.GetCustomAttributes(false).OfType <DisplayNameAttribute>().FirstOrDefault(); string dispName = ""; if (datt != null) { dispName = datt.DisplayName ?? pi.Name; } else { dispName = pi.Name; } tag.InnerText = dispName; } else if (tagType == TagTypes.RadioButton) { tag = new HtmlTag("input", true); tag.Attr("name", mmd.PropertyName); tag.Attr("id", mmd.PropertyName); tag.Attr("type", "radio"); tag.Attr("value", GetHTMLValue(mmd.ModelAccessor())); if (isChecked) { tag.Attr("checked", "checked"); } } else if (tagType == TagTypes.Select) { tag = new HtmlTag("select"); tag.Attr("id", mmd.PropertyName); tag.Attr("name", mmd.PropertyName); if (useLabel) { HtmlTag optx = new HtmlTag("option", new { value = "" }) { InnerText = optionLabel ?? "" }; tag.Children.Add(optx); } if (selectList != null) { foreach (SelectListItem si in selectList) { HtmlTag opt = new HtmlTag("option", new { value = si.Value ?? "" }) { InnerText = si.Text ?? "" }; if (si.Selected) { opt.Attr("selected", "selected"); } tag.Children.Add(opt); } } } else if (tagType == TagTypes.TextArea) { tag = new HtmlTag("textarea"); tag.Attr("cols", "20"); tag.Attr("rows", "2"); tag.Attr("name", mmd.PropertyName); tag.Attr("id", mmd.PropertyName); tag.InnerText = GetHTMLValue(mmd.ModelAccessor()); } else if (tagType == TagTypes.Span) { tag = new HtmlTag("span"); tag.Attr("id", mmd.PropertyName); tag.InnerText = GetHTMLValue(mmd.ModelAccessor()); } //WFUtilities.CheckPropertyError(metadata, model, tag, mmd.PropertyName, mmd.PropertyName); tag.MergeObjectProperties(htmlProperties); if (((MemberExpression)expression.Body).Member is PropertyInfo) { tag = htmlHelper.PreProcess(tag, metadata, tagType, mmd.PropertyName, (PropertyInfo)((MemberExpression)expression.Body).Member, model); } else { throw new Exception("Invalid argument specified in lambda for Html.xFor() method [" + markupName + "] (must be a property). Check your markup."); } return(tag); }
/// <summary> /// Find or create a WFModelMetaProperty for the DataAnnotationValidatorControl. /// The WFModelMetaProperty will be added to the WFModelMetaData object. /// </summary> /// <param name="dvc">The DataAnnotationValidatorControl whose property needs to be added to metadata.</param> /// <param name="metadata">The existing metadata to search through.</param> /// <returns></returns> public static WFModelMetaProperty GetMetaPropertyFromValidator(Control rootControl, DataAnnotationValidatorControl dvc, WFModelMetaData metadata) { Type sourceType = dvc.SourceType; Control controlValidating = WebControlUtilities.FindControlRecursive(rootControl, dvc.ControlToValidate); WFModelMetaProperty metaproperty = metadata.Properties.FirstOrDefault(m => m.MarkupName == controlValidating.UniqueID); if (metaproperty == null) { metaproperty = new WFModelMetaProperty(); metadata.Properties.Add(metaproperty); } metaproperty.PropertyName = dvc.PropertyName; metaproperty.MarkupName = controlValidating.UniqueID; if (String.IsNullOrEmpty(dvc.SourceTypeString)) { if (sourceType == null && String.IsNullOrEmpty(dvc.XmlRuleSetName) && dvc.Page as IWFGetValidationRulesForPage == null) { throw new Exception("The SourceType and SourceTypeString properties are null/empty on one of the validator controls.\r\nPopulate either property.\r\nie: control.SourceType = typeof(Widget); OR in markup SourceTypeString=\"Assembly.Classes.Widget, Assembly\""); } else if (sourceType == null && !String.IsNullOrEmpty(dvc.XmlRuleSetName)) { sourceType = WFUtilities.GetRuleSetForName(dvc.XmlRuleSetName).ModelType; } else if (sourceType == null && String.IsNullOrEmpty(dvc.XmlRuleSetName)) { sourceType = ((IWFGetValidationRulesForPage)dvc.Page).GetValidationClassType(); } } else { try { sourceType = Type.GetType(dvc.SourceTypeString, true, true); } catch (Exception ex) { throw new Exception("Couldn't resolve type " + dvc.SourceTypeString + ". You may need to specify the fully qualified assembly name."); } } PropertyInfo prop = WFUtilities.GetTargetProperty(dvc.PropertyName, sourceType); if (String.IsNullOrEmpty(dvc.XmlRuleSetName)) { foreach (var attr in prop.GetCustomAttributes(typeof(ValidationAttribute), true).OfType <ValidationAttribute>()) { var displayNameAttr = prop.GetCustomAttributes(typeof(DisplayNameAttribute), true).OfType <DisplayNameAttribute>().FirstOrDefault(); string displayName = displayNameAttr == null ? prop.Name : displayNameAttr.DisplayName; if (attr as IWFRequireValueProviderContext != null) { ((IWFRequireValueProviderContext)attr).SetValueProvider(new WFPageControlsValueProvider(dvc.Page, "")); } metaproperty.DisplayName = displayName; metaproperty.ValidationAttributes.Add(attr); if (!attr.IsValid(GetControlValue(controlValidating))) { metaproperty.HasError = true; if (metaproperty.Errors == null) { metaproperty.Errors = new List <string>(); } metaproperty.Errors.Add(attr.FormatErrorMessage(displayName)); } } } else { XmlDataAnnotationsRuleSet ruleset = WFUtilities.GetRuleSetForType(sourceType, dvc.XmlRuleSetName); metaproperty.DisplayName = dvc.PropertyName; try { //It's OK to have a DataAnnotationValidatorControl for a property that has no validation rules //defined in the XML. XmlDataAnnotationsRuleSetProperty property = ruleset.Properties.FirstOrDefault(p => p.PropertyName == dvc.PropertyName); if (property != null) { foreach (var validator in property.Validators) { ValidationAttribute attr = WFUtilities.GetValidatorInstanceForXmlDataAnnotationsValidator(validator); if (attr as IWFRequireValueProviderContext != null) { ((IWFRequireValueProviderContext)attr).SetValueProvider(new WFPageControlsValueProvider(dvc.Page, "")); } foreach (var key in validator.ValidatorAttributes.Keys) { PropertyInfo pi = attr.GetType().GetProperty(key); if (pi != null) { pi.SetValue(attr, Convert.ChangeType(validator.ValidatorAttributes[key], pi.PropertyType), null); } } metaproperty.ValidationAttributes.Add(attr); if (!attr.IsValid(GetControlValue(controlValidating))) { metaproperty.HasError = true; if (metaproperty.Errors == null) { metaproperty.Errors = new List <string>(); } metaproperty.Errors.Add(validator.ErrorMessage); } } } } catch (Exception ex) { throw new Exception("Error trying to validate " + dvc.PropertyName + ", innerexception may have more details...\r\nMake sure ErrorMessage isn't specified in more than one place.", ex); } } return(metaproperty); }