天道酬勤,学无止境

Best way to trim strings after data entry. Should I create a custom model binder?

I'm using ASP.NET MVC and I'd like all user entered string fields to be trimmed before they're inserted into the database. And since I have many data entry forms, I'm looking for an elegant way to trim all strings instead of explicitly trimming every user supplied string value. I'm interested to know how and when people are trimming strings.

I thought about perhaps creating a custom model binder and trimming any string values there...that way, all my trimming logic is contained in one place. Is this a good approach? Are there any code samples that do this?

评论

  public class TrimModelBinder : DefaultModelBinder
  {
    protected override void SetProperty(ControllerContext controllerContext, 
      ModelBindingContext bindingContext, 
      System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
    {
      if (propertyDescriptor.PropertyType == typeof(string))
      {
        var stringValue = (string)value;
        if (!string.IsNullOrWhiteSpace(stringValue))
        {
          value = stringValue.Trim();
        }
        else
        {
          value = null;
        }
      }

      base.SetProperty(controllerContext, bindingContext, 
                          propertyDescriptor, value);
    }
  }

How about this code?

ModelBinders.Binders.DefaultBinder = new TrimModelBinder();

Set global.asax Application_Start event.

This is @takepara same resolution but as an IModelBinder instead of DefaultModelBinder so that adding the modelbinder in global.asax is through

ModelBinders.Binders.Add(typeof(string),new TrimModelBinder());

The class:

public class TrimModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext,
    ModelBindingContext bindingContext)
    {
        ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueResult== null || valueResult.AttemptedValue==null)
           return null;
        else if (valueResult.AttemptedValue == string.Empty)
           return string.Empty;
        return valueResult.AttemptedValue.Trim();
    }
}

based on @haacked post: http://haacked.com/archive/2011/03/19/fixing-binding-to-decimals.aspx

One improvement to @takepara answer.

Somewere in project:

public class NoTrimAttribute : Attribute { }

In TrimModelBinder class change

if (propertyDescriptor.PropertyType == typeof(string))

to

if (propertyDescriptor.PropertyType == typeof(string) && !propertyDescriptor.Attributes.Cast<object>().Any(a => a.GetType() == typeof(NoTrimAttribute)))

and you can mark properties to be excluded from trimming with [NoTrim] attribute.

In ASP.Net Core 2 this worked for me. I'm using the [FromBody] attribute in my controllers and JSON input. To override the string handling in the JSON deserialization I registered my own JsonConverter:

services.AddMvcCore()
    .AddJsonOptions(options =>
        {
            options.SerializerSettings.Converters.Insert(0, new TrimmingStringConverter());
        })

And this is the converter:

public class TrimmingStringConverter : JsonConverter
{
    public override bool CanRead => true;
    public override bool CanWrite => false;

    public override bool CanConvert(Type objectType) => objectType == typeof(string);

    public override object ReadJson(JsonReader reader, Type objectType,
        object existingValue, JsonSerializer serializer)
    {
        if (reader.Value is string value)
        {
            return value.Trim();
        }

        return reader.Value;
    }

    public override void WriteJson(JsonWriter writer, object value,
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

With improvements in C# 6, you can now write a very compact model binder that will trim all string inputs:

public class TrimStringModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        var attemptedValue = value?.AttemptedValue;

        return string.IsNullOrWhiteSpace(attemptedValue) ? attemptedValue : attemptedValue.Trim();
    }
}

You need to include this line somewhere in Application_Start() in your Global.asax.cs file to use the model binder when binding strings:

ModelBinders.Binders.Add(typeof(string), new TrimStringModelBinder());

I find it is better to use a model binder like this, rather than overriding the default model binder, because then it will be used whenever you are binding a string, whether that's directly as a method argument or as a property on a model class. However, if you override the default model binder as other answers here suggest, that will only work when binding properties on models, not when you have a string as an argument to an action method

Edit: a commenter asked about dealing with the situation when a field should not be validated. My original answer was reduced to deal just with the question the OP had posed, but for those who are interested, you can deal with validation by using the following extended model binder:

public class TrimStringModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var shouldPerformRequestValidation = controllerContext.Controller.ValidateRequest && bindingContext.ModelMetadata.RequestValidationEnabled;
        var unvalidatedValueProvider = bindingContext.ValueProvider as IUnvalidatedValueProvider;

        var value = unvalidatedValueProvider == null ?
          bindingContext.ValueProvider.GetValue(bindingContext.ModelName) :
          unvalidatedValueProvider.GetValue(bindingContext.ModelName, !shouldPerformRequestValidation);

        var attemptedValue = value?.AttemptedValue;

        return string.IsNullOrWhiteSpace(attemptedValue) ? attemptedValue : attemptedValue.Trim();
    }
}

Another variant of @takepara's answer but with a different twist:

1) I prefer the opt-in "StringTrim" attribute mechanism (rather than the opt-out "NoTrim" example of @Anton).

2) An additional call to SetModelValue is required to ensure the ModelState is populated correctly and the default validation/accept/reject pattern can be used as normal, i.e. TryUpdateModel(model) to apply and ModelState.Clear() to accept all changes.

Put this in your entity/shared library:

/// <summary>
/// Denotes a data field that should be trimmed during binding, removing any spaces.
/// </summary>
/// <remarks>
/// <para>
/// Support for trimming is implmented in the model binder, as currently
/// Data Annotations provides no mechanism to coerce the value.
/// </para>
/// <para>
/// This attribute does not imply that empty strings should be converted to null.
/// When that is required you must additionally use the <see cref="System.ComponentModel.DataAnnotations.DisplayFormatAttribute.ConvertEmptyStringToNull"/>
/// option to control what happens to empty strings.
/// </para>
/// </remarks>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class StringTrimAttribute : Attribute
{
}

Then this in your MVC application/library:

/// <summary>
/// MVC model binder which trims string values decorated with the <see cref="StringTrimAttribute"/>.
/// </summary>
public class StringTrimModelBinder : IModelBinder
{
    /// <summary>
    /// Binds the model, applying trimming when required.
    /// </summary>
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Get binding value (return null when not present)
        var propertyName = bindingContext.ModelName;
        var originalValueResult = bindingContext.ValueProvider.GetValue(propertyName);
        if (originalValueResult == null)
            return null;
        var boundValue = originalValueResult.AttemptedValue;

        // Trim when required
        if (!String.IsNullOrEmpty(boundValue))
        {
            // Check for trim attribute
            if (bindingContext.ModelMetadata.ContainerType != null)
            {
                var property = bindingContext.ModelMetadata.ContainerType.GetProperties()
                    .FirstOrDefault(propertyInfo => propertyInfo.Name == bindingContext.ModelMetadata.PropertyName);
                if (property != null && property.GetCustomAttributes(true)
                    .OfType<StringTrimAttribute>().Any())
                {
                    // Trim when attribute set
                    boundValue = boundValue.Trim();
                }
            }
        }

        // Register updated "attempted" value with the model state
        bindingContext.ModelState.SetModelValue(propertyName, new ValueProviderResult(
            originalValueResult.RawValue, boundValue, originalValueResult.Culture));

        // Return bound value
        return boundValue;
    }
}

If you don't set the property value in the binder, even when you don't want to change anything, you will block that property from ModelState altogether! This is because you are registered as binding all string types, so it appears (in my testing) that the default binder will not do it for you then.

Extra info for anyone searching how to do this in ASP.NET Core 1.0. Logic has changed quite a lot.

I wrote a blog post about how to do it, it explains things in bit more detailed

So ASP.NET Core 1.0 solution:

Model binder to do the actual trimming

public class TrimmingModelBinder : ComplexTypeModelBinder  
{
    public TrimmingModelBinder(IDictionary propertyBinders) : base(propertyBinders)
    {
    }

    protected override void SetProperty(ModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result)
    {
        if(result.Model is string)
        {
            string resultStr = (result.Model as string).Trim();
            result = ModelBindingResult.Success(resultStr);
        }

        base.SetProperty(bindingContext, modelName, propertyMetadata, result);
    }
}

Also you need Model Binder Provider in the latest version, this tells that should this binder be used for this model

public class TrimmingModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
        {
            var propertyBinders = new Dictionary();
            foreach (var property in context.Metadata.Properties)
            {
                propertyBinders.Add(property, context.CreateBinder(property));
            }

            return new TrimmingModelBinder(propertyBinders);
        }

        return null;
    }
}

Then it has to be registered in Startup.cs

 services.AddMvc().AddMvcOptions(options => {  
       options.ModelBinderProviders.Insert(0, new TrimmingModelBinderProvider());
 });

In case of MVC Core

Binder:

using Microsoft.AspNetCore.Mvc.ModelBinding;
using System;
using System.Threading.Tasks;
public class TrimmingModelBinder
    : IModelBinder
{
    private readonly IModelBinder FallbackBinder;

    public TrimmingModelBinder(IModelBinder fallbackBinder)
    {
        FallbackBinder = fallbackBinder ?? throw new ArgumentNullException(nameof(fallbackBinder));
    }

    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (valueProviderResult != null &&
            valueProviderResult.FirstValue is string str &&
            !string.IsNullOrEmpty(str))
        {
            bindingContext.Result = ModelBindingResult.Success(str.Trim());
            return Task.CompletedTask;
        }

        return FallbackBinder.BindModelAsync(bindingContext);
    }
}

Provider:

using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using System;

public class TrimmingModelBinderProvider
    : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (!context.Metadata.IsComplexType && context.Metadata.ModelType == typeof(string))
        {
            return new TrimmingModelBinder(new SimpleTypeModelBinder(context.Metadata.ModelType));
        }

        return null;
    }
}

Registration function:

    public static void AddStringTrimmingProvider(this MvcOptions option)
    {
        var binderToFind = option.ModelBinderProviders
            .FirstOrDefault(x => x.GetType() == typeof(SimpleTypeModelBinderProvider));

        if (binderToFind == null)
        {
            return;
        }

        var index = option.ModelBinderProviders.IndexOf(binderToFind);
        option.ModelBinderProviders.Insert(index, new TrimmingModelBinderProvider());
    }

Register:

service.AddMvc(option => option.AddStringTrimmingProvider())

While reading through the excellent answers and comments above, and becoming increasingly confused, I suddenly thought, hey, I wonder if there's a jQuery solution. So for others who, like me, find ModelBinders a bit bewildering, I offer the following jQuery snippet that trims the input fields before the form gets submitted.

    $('form').submit(function () {
        $(this).find('input:text').each(function () {
            $(this).val($.trim($(this).val()));
        })
    });

I created value providers to trim the query string parameter values and the form values. This was tested with ASP.NET Core 3 and works perfectly.

public class TrimmedFormValueProvider
    : FormValueProvider
{
    public TrimmedFormValueProvider(IFormCollection values)
        : base(BindingSource.Form, values, CultureInfo.InvariantCulture)
    { }

    public override ValueProviderResult GetValue(string key)
    {
        ValueProviderResult baseResult = base.GetValue(key);
        string[] trimmedValues = baseResult.Values.Select(v => v?.Trim()).ToArray();
        return new ValueProviderResult(new StringValues(trimmedValues));
    }
}

public class TrimmedQueryStringValueProvider
    : QueryStringValueProvider
{
    public TrimmedQueryStringValueProvider(IQueryCollection values)
        : base(BindingSource.Query, values, CultureInfo.InvariantCulture)
    { }

    public override ValueProviderResult GetValue(string key)
    {
        ValueProviderResult baseResult = base.GetValue(key);
        string[] trimmedValues = baseResult.Values.Select(v => v?.Trim()).ToArray();
        return new ValueProviderResult(new StringValues(trimmedValues));
    }
}

public class TrimmedFormValueProviderFactory
    : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        if (context.ActionContext.HttpContext.Request.HasFormContentType)
            context.ValueProviders.Add(new TrimmedFormValueProvider(context.ActionContext.HttpContext.Request.Form));
        return Task.CompletedTask;
    }
}

public class TrimmedQueryStringValueProviderFactory
    : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        context.ValueProviders.Add(new TrimmedQueryStringValueProvider(context.ActionContext.HttpContext.Request.Query));
        return Task.CompletedTask;
    }
}

Then register the value provider factories in the ConfigureServices() function in Startup.cs

services.AddControllersWithViews(options =>
{
    int formValueProviderFactoryIndex = options.ValueProviderFactories.IndexOf(options.ValueProviderFactories.OfType<FormValueProviderFactory>().Single());
    options.ValueProviderFactories[formValueProviderFactoryIndex] = new TrimmedFormValueProviderFactory();

    int queryStringValueProviderFactoryIndex = options.ValueProviderFactories.IndexOf(options.ValueProviderFactories.OfType<QueryStringValueProviderFactory>().Single());
    options.ValueProviderFactories[queryStringValueProviderFactoryIndex] = new TrimmedQueryStringValueProviderFactory();
});

Late to the party, but the following is a summary of adjustments required for MVC 5.2.3 if you are to handle the skipValidation requirement of the build-in value providers.

public class TrimStringModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // First check if request validation is required
        var shouldPerformRequestValidation = controllerContext.Controller.ValidateRequest && 
            bindingContext.ModelMetadata.RequestValidationEnabled;

        // determine if the value provider is IUnvalidatedValueProvider, if it is, pass in the 
        // flag to perform request validation (e.g. [AllowHtml] is set on the property)
        var unvalidatedProvider = bindingContext.ValueProvider as IUnvalidatedValueProvider;

        var valueProviderResult = unvalidatedProvider?.GetValue(bindingContext.ModelName, !shouldPerformRequestValidation) ??
            bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        return valueProviderResult?.AttemptedValue?.Trim();
    }
}

Global.asax

    protected void Application_Start()
    {
        ...
        ModelBinders.Binders.Add(typeof(string), new TrimStringModelBinder());
        ...
    }

I disagree with the solution. You should override GetPropertyValue because the data for SetProperty could also be filled by the ModelState. To catch the raw data from the input elements write this:

 public class CustomModelBinder : System.Web.Mvc.DefaultModelBinder
{
    protected override object GetPropertyValue(System.Web.Mvc.ControllerContext controllerContext, System.Web.Mvc.ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, System.Web.Mvc.IModelBinder propertyBinder)
    {
        object value = base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);

        string retval = value as string;

        return string.IsNullOrWhiteSpace(retval)
                   ? value
                   : retval.Trim();
    }

}

Filter by propertyDescriptor PropertyType if you are really only interested in string values but it should not matter because everything what comes in is basically a string.

For ASP.NET Core, replace the ComplexTypeModelBinderProvider with a provider that trims strings.

In your startup code ConfigureServices method, add this:

services.AddMvc()
    .AddMvcOptions(s => {
        s.ModelBinderProviders[s.ModelBinderProviders.TakeWhile(p => !(p is ComplexTypeModelBinderProvider)).Count()] = new TrimmingModelBinderProvider();
    })

Define TrimmingModelBinderProvider like this:

/// <summary>
/// Used in place of <see cref="ComplexTypeModelBinderProvider"/> to trim beginning and ending whitespace from user input.
/// </summary>
class TrimmingModelBinderProvider : IModelBinderProvider
{
    class TrimmingModelBinder : ComplexTypeModelBinder
    {
        public TrimmingModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders) : base(propertyBinders) { }

        protected override void SetProperty(ModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result)
        {
            var value = result.Model as string;
            if (value != null)
                result = ModelBindingResult.Success(value.Trim());
            base.SetProperty(bindingContext, modelName, propertyMetadata, result);
        }
    }

    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType) {
            var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
            for (var i = 0; i < context.Metadata.Properties.Count; i++) {
                var property = context.Metadata.Properties[i];
                propertyBinders.Add(property, context.CreateBinder(property));
            }
            return new TrimmingModelBinder(propertyBinders);
        }
        return null;
    }
}

The ugly part of this is the copy and paste of the GetBinder logic from ComplexTypeModelBinderProvider, but there doesn't seem to be any hook to let you avoid this.

There have been a lot of posts suggesting an attribute approach. Here is a package that already has a trim attribute and many others: Dado.ComponentModel.Mutations or NuGet

public partial class ApplicationUser
{
    [Trim, ToLower]
    public virtual string UserName { get; set; }
}

// Then to preform mutation
var user = new ApplicationUser() {
    UserName = "   M@X_speed.01! "
}

new MutationContext<ApplicationUser>(user).Mutate();

After the call to Mutate(), user.UserName will be mutated to m@x_speed.01!.

This example will trim whitespace and case the string to lowercase. It doesn't introduce validation, but the System.ComponentModel.Annotations can be used alongside Dado.ComponentModel.Mutations.

I posted this in another thread. In asp.net core 2, I went in a different direction. I used an action filter instead. In this case the developer can either set it globally or use as an attribute for the actions he/she wants to apply the string trimming. This code runs after the model binding has taken place, and it can update the values in the model object.

Here is my code, first create an action filter:

public class TrimInputStringsAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        foreach (var arg in context.ActionArguments)
        {
            if (arg.Value is string)
            {
                string val = arg.Value as string;
                if (!string.IsNullOrEmpty(val))
                {
                    context.ActionArguments[arg.Key] = val.Trim();
                }

                continue;
            }

            Type argType = arg.Value.GetType();
            if (!argType.IsClass)
            {
                continue;
            }

            TrimAllStringsInObject(arg.Value, argType);
        }
    }

    private void TrimAllStringsInObject(object arg, Type argType)
    {
        var stringProperties = argType.GetProperties()
                                      .Where(p => p.PropertyType == typeof(string));

        foreach (var stringProperty in stringProperties)
        {
            string currentValue = stringProperty.GetValue(arg, null) as string;
            if (!string.IsNullOrEmpty(currentValue))
            {
                stringProperty.SetValue(arg, currentValue.Trim(), null);
            }
        }
    }
}

To use it, either register as global filter or decorate your actions with the TrimInputStrings attribute.

[TrimInputStrings]
public IActionResult Register(RegisterViewModel registerModel)
{
    // Some business logic...
    return Ok();
}

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 数据输入后修剪字符串的最佳方法。 我应该创建自定义模型活页夹吗?(Best way to trim strings after data entry. Should I create a custom model binder?)
    问题 我正在使用ASP.NET MVC,我希望在将所有用户输入的字符串字段插入数据库之前先对其进行修剪。 并且由于我有许多数据输入表单,因此我正在寻找一种修整所有字符串的方法,而不是显式修整每个用户提供的字符串值。 我很想知道人们如何以及何时修剪琴弦。 我考虑过可能要创建一个自定义模型联编程序并在那里修剪任何字符串值...那样,我所有的修剪逻辑都包含在一个地方。 这是一个好方法吗? 是否有任何代码示例可以做到这一点? 回答1 public class TrimModelBinder : DefaultModelBinder { protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value) { if (propertyDescriptor.PropertyType == typeof(string)) { var stringValue = (string)value; if (!string.IsNullOrWhiteSpace(stringValue)) { value =
  • ASP.NET MVC - Mixing Custom and Default Model Binding
    I have a type: public class IssueForm { Order Order {get; set;} Item Item {get; set;} Range Range {get; set;} } I created a custom model binder due to requirements on Order and Item, but Range could still use the Default Model Binder. Is there a way from within my custom model binder to call the default model binder to return a Range object? I think I just have to just setup ModelBindingContext correctly, but I don't know how. EDIT Looking at the first comment and answer -- it seems like inheriting from the default model binder could be useful. To add more specifics for my setup so far I have
  • Custom model binder for a property
    I have the following controller action: [HttpPost] public ViewResult DoSomething(MyModel model) { // do something return View(); } Where MyModel looks like this: public class MyModel { public string PropertyA {get; set;} public IList<int> PropertyB {get; set;} } So DefaultModelBinder should bind this without a problem. The only thing is that I want to use special/custom binder for binding PropertyB and I also want to reuse this binder. So I thought that solution would be to put a ModelBinder attribute before the PropertyB which of course doesn't work (ModelBinder attribute is not allowed on a
  • Asp.Net MVC 2 - Bind a model's property to a different named value
    Update (21st Sept 2016) - Thanks to Digbyswift for commenting that this solution still works in MVC5 also. Update (30th April 2012) - Note to people stumbling across this question from searches etc - the accepted answer is not how I ended up doing this - but I left it accepted because it might have worked in some cases. My own answer contains the final solution I used, which is reusable and will apply to any project. It's also confirmed to work in v3 and v4 of the MVC framework. I have the following model type (the names of the class and its properties have been changed to protect their
  • Proper way to use AJAX Post in jquery to pass model from strongly typed MVC3 view
    I'm a novice web programmer so please forgive me if some of my "jargon" is not correct. I've got a project using ASP.NET using the MVC3 framework. I am working on an admin view where the admin will modify a list of equipment. One of the functions is an "update" button that I want to use jquery to dynamically edit the entry on the webpage after sending a post to the MVC controller. I presume this approach is "safe" in a single admin setting where there is minimal concern of the webpage getting out of sync with the database. I've created a view that is strongly typed and was hoping to pass the
  • Polymorphic model binding
    This question has been asked before in earlier versions of MVC. There is also this blog entry about a way to work around the problem. I'm wondering if MVC3 has introduced anything that might help, or if there are any other options. In a nutshell. Here's the situation. I have an abstract base model, and 2 concrete subclasses. I have a strongly typed view that renders the models with EditorForModel(). Then I have custom templates to render each concrete type. The problem comes at post time. If I make the post action method take the base class as the parameter, then MVC can't create an abstract
  • Correct, idiomatic way to use custom editor templates with IEnumerable models in ASP.NET MVC
    This question is a follow-up for Why is my DisplayFor not looping through my IEnumerable<DateTime>? A quick refresh. When: the model has a property of type IEnumerable<T> you pass this property to Html.EditorFor() using the overload that only accepts the lambda expression you have an editor template for the type T under Views/Shared/EditorTemplates then the MVC engine will automatically invoke the editor template for each item in the enumerable sequence, producing a list of the results. E.g., when there is a model class Order with property Lines: public class Order { public IEnumerable
  • Spring 3.0 MVC binding Enums Case Sensitive
    If I have a RequestMapping in a Spring controller like so... @RequestMapping(method = RequestMethod.GET, value = "{product}") public ModelAndView getPage(@PathVariable Product product) And Product is an enum. eg. Product.Home When I request the page, mysite.com/home I get Unable to convert value "home" from type 'java.lang.String' to type 'domain.model.product.Product'; nested exception is java.lang.IllegalArgumentException: No enum const class domain.model.product.Product.home Is there a way to have the enum type converter to understand that lower case home is actually Home? I'd like to keep
  • Correct way to implement a custom popup tkinter dialog box
    I just started learning how to create a custom pop up dialog box; and as it turns out, the tkinter messagebox is really easy to use, but it also does not do too much. Here is my attempt to create a dialog box that will take input and then store that in the username. My question is what is the recommended style to implement this? As Bryan Oakley suggested in this comment. I would advise against using a global variable. Instead of having the dialog destroy itself, have it destroy only the actual widget but leave the object alive. Then, call something like inputDialog.get_string() and then del
  • MVC 3 Model Binding a Sub Type (Abstract Class or Interface)
    Say I have a Product model, the Product model has a property of ProductSubType (abstract) and we have two concrete implementations Shirt and Pants. Here is the source: public class Product { public int Id { get; set; } [Required] public string Name { get; set; } [Required] public decimal? Price { get; set; } [Required] public int? ProductType { get; set; } public ProductTypeBase SubProduct { get; set; } } public abstract class ProductTypeBase { } public class Shirt : ProductTypeBase { [Required] public string Color { get; set; } public bool HasSleeves { get; set; } } public class Pants
  • custom_preprocessing
    When you would like to interfere with the way resampling during preprocessing is handled or you would like to implement a custom normalization scheme, you need to create a new custom preprocessor class and an ExperimentPlanner to go along with it. While this may appear cumbersome, the great thing about this approach is that the same code will be used for inference as well thus guaranteeing that images are preprocessed properly (i.e. the way the model expects). In this tutorial we will implement a custom normalization scheme for the Task120 Massachusetts Road Segmentation. Make sure to download
  • ASP.NET MVC Model Binder for Generic Type
    Is it possible to create a model binder for a generic type? For example, if I have a type public class MyType<T> Is there any way to create a custom model binder that will work for any type of MyType? Thanks, Nathan
  • Custom DateTime model binder in Asp.net MVC
    I would like to write my own model binder for DateTime type. First of all I'd like to write a new attribute that I can attach to my model property like: [DateTimeFormat("d.M.yyyy")] public DateTime Birth { get; set,} This is the easy part. But the binder part is a bit more difficult. I would like to add a new model binder for type DateTime. I can either implement IModelBinder interface and write my own BindModel() method inherit from DefaultModelBinder and override BindModel() method My model has a property as seen above (Birth). So when the model tries to bind request data to this property
  • 小记spring-boot自动加载
    自动配置: 通过 @EnableAutoConfiguration 或者@SpringBootApplication注解 开启组件扫描和自动配置 通过@SpringBootApplication(exclude = XAutoConfiguration.class)关闭自动配置,自动配置位于 org.springframework.boot.autoconfigure包路径。 有一个名为getAutoConfigurationEntry的方法,这个方法发挥的作用是扫描ClassPath下的所有jar包的spring.factories文件,将spring.factories文件key为EnableAutoConfiguration的所有值取出,然后这些值其实是类的全限定名,也就是自动配置类的全限定名,然后 Spring Boot 通过这些全限定名进行类加载(反射),将这些自动配置类添加到 Spring 容器中 /** * 加载AutoConfigurationImportSelector */ @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { ... /**
  • JsonValueProviderFactory throws “request too large”
    I'm getting an exception that the JSON request was too large to be deserialized. It's coming from the JsonValueProviderFactory.... The MVC App currently has a custom model binder using Json.Net which has no problem deserializing the json data. However I'm assuming the default JSON value provider is tripping up? or has some weird limit built into it? It may be be to do with the latest release of MVC4 as when using the previous build of MVC4 there were no problems with large amounts of JSON. So, is there a way to change the setting s of the actual json value binder? going by http://haacked.com
  • ASP.Net MVC Custom Model Binding explanation [closed]
    Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers. Want to improve this question? Update the question so it's on-topic for Stack Overflow. Closed 6 years ago. Improve this question Is anyone aware of where I can find a tutorial for building a custom model binder. I have found several issues using the default model binder with EntitySets (not populating when creating new objects and creating duplicates on editing objects) and find that my UI doesn't match my model exactly (e.g. time fields formated "hh:mm am" do not match with a timespan). I
  • Is this the way to validate Django model fields?
    As I understand it, when one creates a Django application, data is validated by the form before it's inserted into a model instance which is then written to the database. But if I want to create an additional layer of protection at the data model layer, is what I've done below the current "best practice?" I'm trying to ensure that a reviewer's name cannot be omitted nor be left blank. Should I be putting any custom validation in the 'clean' method as I've done here and then have 'save' call 'full_clean" which calls 'clean'? If not, what's the preferred method? Thanks. class Reviewer(models
  • ASP.Net MVC: Calling a method from a view
    In my MVC app the controller gets the data (model) from an external API (so there is no model class being used) and passes that to the view. The data (model) has a container in which there are several objects with several fields (string values). One view iterates over each object and calls another view to draw each of them. This view iterates over the fields (string values) and draws them. Here's where it gets tricky for me. Sometimes I want to do some special formatting on the fields (string values). I could write 20 lines of code for the formatting but then I would have to do that for each
  • Working with several custom table models avoiding repetitive code
    I'm working in a project in which we have several domain classes to model business data. Those classes are simple POJO's and I have to display several tables using them. For example, consider this class: public class Customer { private Long id; private Date entryDate; private String name; private String address; private String phoneNumber; public Customer(Long id, Date entryDate, String name, String address, String phoneNumber) { this.id = id; this.entryDate = entryDate; this.nombre = name; this.domicilio = address; this.telefono = phoneNumber; } // Getters and setters here } I have created
  • Correctly implementing the MVC pattern in GUI development using Swing in Java
    Firstly, I come from a big PHP background with MVC, when I started with PHP, I browsed a lot of times, to try my best and perfect my MVC-Like design in PHP. A lot of people like answered with answers which helped me a lot. But after starting GUI development in Swing, the answers about MVC in Swing are totally different. For instance, a model is also a view? According to Oracle's Suggestions TextElementModel doesn't have any logical business here, all it does is markup (set color etc) and setting data such as set text and so on. When I developed in PHP, there is no such thing as AbstractModel