views:

909

answers:

3

I am attempting to upgrade my MVC 1 project to MVC 2 RC. We currently have a custom modelbinder that adds items to the ValueProvider (this worked when it was a dictionary). We then passed this off to the default modelbinder. However, IValueProvider does not have an add method, so this algorithm no longer works. Does anyone know of a way to add values to the ValueProvider in MVC 2?

foreach(string valKey in controllerContext.RequestContext.HttpContext.Request.Form.AllKeys.Where(x => x.StartsWith(valuesToChangePrefix)))
{
    string valName = valKey.Substring(valuesToChangePrefix.Length);

    string myVal = ManipulateValue(bindingContext.ValueProvider.GetValue(valKey).AttemptedValue);

    // This is where I need to add to my value Provider (As you can see I used to just assign a ValueProviderResult
    //bindingContext.ValueProvider = new ValueProviderResult(myVal.Split(','), myVal, bindingContext.ValueProvider.GetValue(valKey).Culture);
}
A: 

Can't you use one of the derived types of IValueProvider? (or even create your own, but there seems to be decent implementations in the framework)

ValueProviderDictionary. ValueProviderCollection, FormCollection (and a couple more) they all implement IValueProvider.

I am not sure if it helps. I am not entirely sure of what you are trying to do. I didn't have to deal with mingling with the post params that much.

Maxwell Troy Milton King
You can use a derived type of IValueProvider, but you have to wire that up further up the pipeline.
Keith Rousseau
The first two have been deprecated.
Martin
The MSDN page does say that `ValueProviderDictionary` is deprecated, but I didn't see where it says the `ValueProviderCollection` is?
Funka
A: 

I probably get you wrong, but what is this prefix you're using? Is that related to a child relation of your model?

If not, why not derive from the DefaultModelBinder and override the BindModel() method? That way, you can call base.BindModel() and manipulate the values afterwards, however you can't use model validation then (make sure you read http://bradwilson.typepad.com/blog/2010/01/input-validation-vs-model-validation-in-aspnet-mvc.html, because there will be a significant change in the release vs. the RC).

The cleaner approach, from what I can guess you try to do, is to use a ViewModel in this case. Since the manipulation is probably non-trivial, you might want to separate input and model validation from each other.

Not sure if this helps either...

mnemosyn
Basically, I'm trying to decrypt values that have a certain prefix. We are trying to make it so that our ViewModels don't know about the decryption - they just have an int and by the time it gets to them it has been decrypted. So, no this does not solve the problem.
Keith Rousseau
+1  A: 

The problem is that by the time you get to the ModelBinder, your ValueProvider has already been set. Previously, you could add values to your ValueProvider at this point.

In order to provide a Custom ValueProvider, you need to override the ControllerActionInvoker, which is the ultimate solution. Unfortunately the ControllerActionInvoker is created by the Controller object, instead of being injected. Therefore, you also need to override Controller to call your own ControllerActionInvoker.

Keith Rousseau
It looks like there is actually an easier solution. You can simply create your own ValueProvider and add it to the static ValueProviderFactories.Factories collection in Application_Start.
Keith Rousseau