2017-02-19 12 views
9

のカスタムモデルバインダーを作成します。私は以下のモデルを持っているASP.NET CORE 1.1プロジェクトにカスタム型

public class GetProductsModel { 
    public OrderExpression OrderBy { get; set; } 
} 

OrderExpressionには、次のメソッドを持つクラスです。

Boolean TryParse(String value, out OrderExpression expression) 

をこの方法は、StringからOrderExpressionインスタンスを作成し、使用することができる。

OrderExpression expression; 

Boolean parsed = OrderExpression.TryParse(value, out expression); 

H私は、タイプOrderExpressionのプロパティにカスタムモデルバインダーを作成できますか?

+0

OrderExpressionのプロパティをバインドしようとしていますか、またはOrderExpressionをコントローラへの入力にバインドしようとしていますか/ action、これは文字列の入力となり、OrderExpressionオブジェクトにマップされますか? –

+0

@AshleyLee OrderExpressionをコントローラアクションの入力にバインドしようとしています...これが役に立ちますか? –

+0

@MiguelMoura、あなたが私の提案された解決策を試す機会があるかどうか疑問に思っていますか? –

答えて

5

私はあなたの要求データ内のおOrderExpression.TryParseを使用してOrderExpressionにバインドするプロパティorderByがあることを前提としています。

のは、以下のようなあなたのOrderExpressionクラスが見えると仮定しましょう、私はあなたのTryParse方法の非常に単純な実装提供している場所:そして、あなたは基本的に生の文字列値とのコールを取得するモデルバインダーを作成することができ

public class OrderExpression 
{ 
    public string RawValue { get; set; } 
    public static bool TryParse(string value, out OrderExpression expr) 
    { 
     expr = new OrderExpression { RawValue = value }; 
     return true; 
    } 
} 

OrderExpression.TryParse

public class OrderExpressionBinder : IModelBinder 
{ 
    public Task BindModelAsync(ModelBindingContext bindingContext) 
    {    
     var values = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
     if (values.Length == 0) return Task.CompletedTask; 

     // Attempt to parse 
     var stringValue = values.FirstValue; 
     OrderExpression expression; 
     if (OrderExpression.TryParse(stringValue, out expression)) 
     { 
      bindingContext.ModelState.SetModelValue(bindingContext.ModelName, expression, stringValue); 
      bindingContext.Result = ModelBindingResult.Success(expression); 
     } 

     return Task.CompletedTask; 
    } 
} 

あなたはまた、単にOrderExpressionタイプのために、あなたの新しいバインダーを返す新しいモデルバインダープロバイダーが、必要になります。

public class OrderExpressionBinderProvider : IModelBinderProvider 
{ 
    public IModelBinder GetBinder(ModelBinderProviderContext context) 
    { 
     return context.Metadata.ModelType == typeof(OrderExpression) ? new OrderExpressionBinder() : null; 
    } 
} 

// It should be registered in your Startup class, adding it to the ModelBinderProviders collection: 
services.AddMvc(opts => { 
    opts.ModelBinderProviders.Insert(0, new OrderExpressionBinderProvider()); 
}); 

これを使用すると、OrderExpressionコントローラのアクションのパラメータをバインドすることができます。次の例のような何か:

[HttpPost] 
public IActionResult Products([FromBody]OrderExpression orderBy) 
{ 
    return Ok(); 
} 

$.ajax({ 
    method: 'POST', 
    dataType: 'json', 
    url: '/home/products', 
    data: {orderby: 'my orderby expression'} 
}); 

しかしJSONを送信し、内部OrderExpressionが含まれていGetProductsModelのような複雑なモデルにバインドすることができるようにあなたのために行われる必要がある何か他のものがあります。私はこのようなシナリオについて話しています:

[HttpPost] 
public IActionResult Products([FromBody]GetProductsModel model) 
{ 
    return Ok(); 
} 

public class GetProductsModel 
{ 
    public OrderExpression OrderBy { get; set; } 
} 

$.ajax({ 
    method: 'POST', 
    dataType: 'json', 
    contentType: 'application/json; charset=utf-8', 
    url: '/home/products', 
    data: JSON.stringify({orderby: 'my orderby expression'}) 
}); 

をそのシナリオでASP.NetコアはちょうどInputFormatterとしてNewtonsoft.Jsonを使用してGetProductsModelモデルのインスタンスに受け取ったJSONに変換されます、使用しようとすることなく、内部プロパティの新しいOrderExpressionBinderProvider

幸いにも、あなたもあなたのJsonConverterを作成することにより、OrderExpressionタイプのプロパティをフォーマットする方法Newtonsoft.Jsonを伝えることができます:今

services.AddMvc(opts => { 
    opts.ModelBinderProviders.Insert(0, new OrderExpressionBinderProvider()); 

}).AddJsonOptions(opts => { 
    opts.SerializerSettings.Converters.Add(new OrderExpressionJsonConverter()); 
}); 

あなたを:スタートアップクラスに登録する必要があります

public class OrderExpressionJsonConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(OrderExpression); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var stringValue = reader.Value?.ToString(); 
     OrderExpression expression; 
     if (OrderExpression.TryParse(stringValue, out expression)) 
     { 
      return expression; 
     } 
     return null; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

最後に両方のシナリオを処理できるようになります:)

関連する問題