@takepara의 답변의 또 다른 변형이지만 다른 변형이 있습니다.
1) 옵트 인 "StringTrim"속성 메커니즘 (@Anton의 옵트 아웃 "NoTrim"예제 대신)을 선호합니다.
2) ModelState가 올바르게 채워지고 기본 유효성 검사 / 수락 / 거부 패턴이 정상적으로 사용되도록 (예 : TryUpdateModel (model) 적용 및 ModelState.Clear () 모든 변경 사항을 적용하려면 SetModelValue에 대한 추가 호출이 필요합니다.
이것을 엔티티 / 공유 라이브러리에 넣으십시오.
/// <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
{
}
그런 다음 MVC 응용 프로그램 / 라이브러리에서 다음을 수행하십시오.
/// <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;
}
}
바인더에서 속성 값을 설정하지 않으면 아무 것도 변경하지 않으려는 경우에도 ModelState에서 해당 속성을 모두 차단합니다! 이것은 모든 문자열 유형을 바인딩하는 것으로 등록되어 있기 때문에 (내 테스트에서) 기본 바인더가 대신하지 않는 것으로 나타납니다.