I have and issue binding to my model with an action filter using reflection. The problem im having is I cannot access the sub class to set the value to a property –> FilePath (string).
Here are the goals I wanted to achive.
1) Upload images using an action filter so I dont reference the HttpContext in my controller action.
2) Force consistancy as all of my models using this method will have to inherit from a generic base abstract class BaseModel<T>.
3) Automatically bind file paths to the model entity
The generic type entity of BaseModel<T> is implementing an interface (IUpload) which will force the use of the property I want to be able to set (FilePath) for further consistancy and generics.
Here is my binding attempt within my action filter…
private void MyCustomBindVoid(ActionExecutingContext filterContext, string filePath)
{
foreach (object x in filterContext.ActionParameters.Values)
{
Type baseType = GetGenericTypeBase(x.GetType(), typeof(BaseModel<>));
if (baseType == null)
{
throw new NullReferenceException("All view models must inherit from the BaseModel abstract class.");
}
foreach (PropertyInfo prop in baseType.GetProperties())
{
Type entity = Type.GetType(prop.PropertyType.AssemblyQualifiedName, true, false);
if (entity != null)
{
foreach (Type i in entity.FindInterfaces((type, criteria) => true, null))
{
if (i == typeof(IUpload))
{
foreach (MemberInfo info in i.GetMembers())
{
PropertyInfo entityInfo = entity.GetProperty(info.Name);
if (entityInfo != null)
{
entityInfo.SetValue("I_CANNOT_FIGURE_HOW_TO_GET_THE_OBJECT_TO_BIND_HERE", filePath, null);
return;
}
}
}
}
}
}
}
}
private Type GetGenericTypeBase(Type type, Type genericType)
{
while (type != typeof(object))
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == genericType)
{
return type;
}
type = type.BaseType;
}
return null;
}
I know its not ideal model binding in the action filter but I have run out of ideas of passing the file path to the model.
This does seem to work and I’ve acomplished this by putting a FilePath (string) property onto the model which is inheriting from BaseModel<T> which can be accessed by the following. As the “x” object is available as a concreate instance.
foreach (MemberInfo info in i.GetMembers())
{
PropertyInfo baseInfo = baseType.GetProperty(info.Name);
if (baseInfo != null)
{
baseInfo.SetValue(x, filePath, null);
return;
}
}
This again will lead to writing the same code in my controller action as i will have to manually set the FilePath property on the BaseModel<T> to the FilePath property of the entity <T>.
Any help will be very much appreciated (Even if it means a drastic rethink)
Found what I was looking for courtesy of http://codecallback.com/
The full explaination can be found below.
http://codecallback.com/forum/3/thread/4/asp-net-mvc-3-model-binding-to-sub-class-with-action-filter-using-reflection
All I need to do was to create an instance of the sub class like so.
Doing this will allow me to decorate my action with a [UploadFileAttribute(param, param)] and let all the file upload, path generation and binding to the property of the generic entity model get taken care of so all I had to do was call MyRepository.Create(Model.Entity);