2017-02-19 121 views
9

在ASP.NET 1.1 CORE項目,我有以下型號:創建自定義模型綁定爲一個自定義類型

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); 

ħ我可以創建一個自定義模型綁定器到OrderExpression類型的屬性嗎?

+0

您是否嘗試綁定OrderExpression的屬性,或者您是否嘗試將OrderExpression綁定到控制器的輸入/ action,這將是一個字符串輸入,然後映射到一個OrderExpression對象? –

+0

@AshleyLee我正在嘗試將OrderExpression綁定到控制器操作的輸入...這有幫助嗎? –

+0

@MiguelMoura,只是想知道你是否有機會嘗試我提出的解決方案? –

回答

5

我假設您的請求數據中有一個屬性orderBy,您想使用OrderExpression.TryParse綁定到OrderExpression

讓我們假設你的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並將其綁定到像GetProductsModel一個複雜的模型,它內部包含一個OrderExpression。我講的一個場景是這樣的:

[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核心將只使用Newtonsoft.Json作爲InputFormatter和接收到的JSON轉換成GetProductsModel模型的實例,但不嘗試使用新的內部財產OrderExpressionBinderProvider

幸運的是,你還可以告訴Newtonsoft.Json如何通過創建JsonConverter格式化OrderExpression類型的屬性:

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(); 
    } 
} 

應在您的啓動類註冊:

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

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

現在你將最終能夠處理這兩種情況:)