ASP.Net l'API Web personnalisé modèle de liaison avec x-www-form-urlencoded données publiées - rien ne semble fonctionner

Je vais avoir beaucoup de mal à faire la coutume de la liaison de modèle de travail lors de la publication x-www-form-urlencoded de données. J'ai essayé tous les moyens, je pense, et rien ne semble pour produire le résultat désiré. Remarque lors de la publication des données JSON, mon JsonConverters et ainsi de suite tout le travail tout aussi bien. C'est quand je poste comme x-www-form-urlencoded que le système n'arrive pas à comprendre comment lier mon modèle.

Mon cas de test, c'est que j'aimerais lier un TimeZoneInfo objet dans le cadre de mon modèle.

Voici mon modèle de classeur:

public class TimeZoneModelBinder : SystemizerModelBinder
{
    protected override object BindModel(string attemptedValue, Action<string> addModelError)
    {
        try
        {
            return TimeZoneInfo.FindSystemTimeZoneById(attemptedValue);
        }
        catch(TimeZoneNotFoundException)
        {
            addModelError("The value was not a valid time zone ID. See the GetSupportedTimeZones Api call for a list of valid time zone IDs.");
            return null;
        }
    }
}

Voici la classe de base que j'utilise:

public abstract class SystemizerModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var name = GetModelName(bindingContext.ModelName);
        var valueProviderResult = bindingContext.ValueProvider.GetValue(name);
        if(valueProviderResult == null || string.IsNullOrWhiteSpace(valueProviderResult.AttemptedValue))
            return false;

        var success = true;
        var value = BindModel(valueProviderResult.AttemptedValue, s =>
        {
            success = false;
            bindingContext.ModelState.AddModelError(name, s);
        });
        bindingContext.Model = value;
        bindingContext.ModelState.SetModelValue(name, new System.Web.Http.ValueProviders.ValueProviderResult(value, valueProviderResult.AttemptedValue, valueProviderResult.Culture));
        return success;
    }

    private string GetModelName(string name)
    {
        var n = name.LastIndexOf(".", StringComparison.Ordinal);
        return n < 0 || n >= name.Length - 1 ? name : name.Substring(n + 1);
    }

    protected abstract object BindModel(string attemptedValue, Action<string> addModelError);
}

J'ai utilisé une classe de base de ce genre pour le rendre simple pour créer des modèles personnalisés liants.

Voici mon modèle de classeur fournisseur. Notez que c'est chargé correctement de mon conteneur IoC, donc je ne vais pas la peine de montrer cet aspect de mon code.

public class SystemizerModelBinderProvider : ModelBinderProvider
{
    public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType)
    {
        if(modelType == typeof(TimeZoneInfo))
            return new TimeZoneModelBinder();

        return null;
    }
}

Enfin, voici la méthode de l'action et de la classe du modèle:

[DataContract)]
public class TestModel
{
    [DataMember]
    public TimeZoneInfo TimeZone { get; set; }
}

[HttpPost]
public HttpResponseMessage Test(TestModel model)
{
    return Request.CreateResponse(HttpStatusCode.OK, model);
}

Pour la méthode de l'action, j'ai essayé:

public HttpResponseMessage Test([FromBody] TestModel model)

Ce invoque le FormUrlEncodedMediaFormatter, qui semble l'ignorer mon classeur de modèles personnalisées tout simplement.

public HttpResponseMessage Test([ModelBinder] TestModel model)

C'est mon modèle de liaison personnalisé, comme prévu, mais il ne fournit ValueProviders pour RouteData et QueryString et pour quelque raison n'est pas de fournir quoi que ce soit pour le contenu du corps. Voir ci-dessous:

ASP.Net l'API Web personnalisé modèle de liaison avec x-www-form-urlencoded données publiées - rien ne semble fonctionner

J'ai aussi essayé la décoration de la classe elle-même avec ModelBinder(typeof(SystemizerModelBinderProvider))

Pourquoi la liaison de modèle se produire UNIQUEMENT lorsque j'utilise le [ModelBinder] attribut, et pourquoi est-ce SEULEMENT essayer de lire la route et de la chaîne de recherche de valeurs et d'ignorer le contenu du corps? Pourquoi ne FromBody ignorer mon modèle de liaison personnalisé fournisseur?

Comment puis-je créer un scénario où je peux recevoir POSTÉ x-www-form-urlencoded de données et de réussir à lier les propriétés du modèle à l'aide de la logique personnalisée?

Juste par curiosité, avez-vous utiliser resharper?

OriginalL'auteur Nathan Ridley | 2013-02-13