Skip to content

Instantly share code, notes, and snippets.

@0biWanKenobi
Forked from ToineSeiter/AliasBinder
Last active July 8, 2022 12:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save 0biWanKenobi/636f74f53b058da8687ff5bf82294075 to your computer and use it in GitHub Desktop.
Save 0biWanKenobi/636f74f53b058da8687ff5bf82294075 to your computer and use it in GitHub Desktop.
Bind form-urlencoded values to property alias
using System;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
namespace Sample
{
[AttributeUsage(AttributeTargets.Property)]
public class AliasAttribute : Attribute
{
internal protected string Name { get; set; }
public AliasAttribute(string name)
{
Name = name;
}
}
public class AliasBinder : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
{
var alias = propertyDescriptor.Attributes
.OfType<AliasAttribute>()
.FirstOrDefault();
string text = CreateSubPropertyName(bindingContext.ModelName, alias?.Name ?? propertyDescriptor.Name);
if (!bindingContext.ValueProvider.ContainsPrefix(text))
{
return;
}
IModelBinder binder = Binders.GetBinder(propertyDescriptor.PropertyType);
object value = propertyDescriptor.GetValue(bindingContext.Model);
ModelMetadata modelMetadata = bindingContext.PropertyMetadata[propertyDescriptor.Name];
modelMetadata.Model = value;
ModelBindingContext bindingContext2 = new ModelBindingContext
{
ModelMetadata = modelMetadata,
ModelName = text,
ModelState = bindingContext.ModelState,
ValueProvider = bindingContext.ValueProvider
};
object propertyValue = GetPropertyValue(controllerContext, bindingContext2, propertyDescriptor, binder);
modelMetadata.Model = propertyValue;
ModelState modelState = bindingContext.ModelState[text];
if (modelState == null || modelState.Errors.Count == 0)
{
if (OnPropertyValidating(controllerContext, bindingContext, propertyDescriptor, propertyValue))
{
SetProperty(controllerContext, bindingContext, propertyDescriptor, propertyValue);
OnPropertyValidated(controllerContext, bindingContext, propertyDescriptor, propertyValue);
return;
}
}
else
{
SetProperty(controllerContext, bindingContext, propertyDescriptor, propertyValue);
foreach (ModelError current in (from err in modelState.Errors
where string.IsNullOrEmpty(err.ErrorMessage) && err.Exception != null
select err).ToList())
{
for (Exception ex = current.Exception; ex != null; ex = ex.InnerException)
{
if (ex is FormatException)
{
string displayName = modelMetadata.GetDisplayName();
string errorMessage = string.Format(CultureInfo.CurrentCulture, $"'{0}' is not valid for field {1}.", modelState.Value.AttemptedValue, displayName);
modelState.Errors.Remove(current);
modelState.Errors.Add(errorMessage);
break;
}
}
}
}
}
}
}
public class AliasBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(Type modelType)
{
var receivedContentType = System.Web.HttpContext.Current.Request.ContentType.ToLower();
var isFormUrlEncoded = receivedContentType == "application/x-www-form-urlencoded";
if(
isFormUrlEncoded
&& Attribute.GetCustomAttribute(modelType, typeof(ModelBinderAttribute)) is ModelBinderAttribute mbAttribute
&& mbAttribute.BinderType == typeof(AliasBinder)
)
{
return new AliasBinder();
}
return null;
}
}
protected void Application_Start()
{
/****rest of configuration****/
ModelBinderProviders.BinderProviders.Insert(0, new AliasBinderProvider());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment