2013-11-20 17 views
5

我試圖張貼到從客戶端的Web API方法,如下所示:POST與IEnumerable的<Interface>類型參數的Web API行動

// Create list of messages that will be sent 
IEnumerable<IMessageApiEntity> messages = new List<IMessageApiEntity>(); 
// Add messages to the list here. 
// They are all different types that implement the IMessageApiEntity interface. 

// Create http client 
HttpClient client = new HttpClient {BaseAddress = new Uri(ConfigurationManager.AppSettings["WebApiUrl"])}; 
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

// Post to web api 
HttpResponseMessage response = client.PostAsJsonAsync("Communications/Messages", messages).Result; 

// Read results 
IEnumerable<ApiResponse<IMessageApiEntity>> results = response.Content.ReadAsAsync<IEnumerable<ApiResponse<IMessageApiEntity>>>().Result; 

我的Web API控制器動作看起來是這樣的:

public HttpResponseMessage Post([FromBody]IEnumerable<IMessageApiEntity> messages) 
{ 
    // Do stuff 
} 

我遇到的問題是,當進入Web API控制器動作時,messages始終爲空(但不爲空)。我在調試器中驗證過,客戶端上的messages對象在發佈之前確實有其中的項目。

我懷疑它可能與嘗試傳遞對象時未將接口類型轉換爲具體類型有關,但我不知道如何使其工作。我怎樣才能做到這一點?

回答

7

我想出瞭如何在沒有自定義模型綁定的情況下做到這一點。發佈的情況下,任何人的回答這個問題......

客戶:

// Create list of messages that will be sent 
IEnumerable<IMessageApiEntity> messages = new List<IMessageApiEntity>(); 
// Add messages to the list here. 
// They are all different types that implement the IMessageApiEntity interface. 

// Create http client 
HttpClient client = new HttpClient {BaseAddress = new Uri(ConfigurationManager.AppSettings["WebApiUrl"])}; 
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

// Post to web api (this is the part that changed) 
JsonMediaTypeFormatter json = new JsonMediaTypeFormatter 
{ 
    SerializerSettings = 
    { 
     TypeNameHandling = TypeNameHandling.All 
    } 
}; 
HttpResponseMessage response = client.PostAsync("Communications/Messages", messages, json).Result; 

// Read results 
IEnumerable<ApiResponse<IMessageApiEntity>> results = response.Content.ReadAsAsync<IEnumerable<ApiResponse<IMessageApiEntity>>>().Result; 

添加到Register方法WebApiConfig.cs:

config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto; 

關鍵是要送類型部分json並打開自動類型名稱處理,以便Web API可以找出它的類型。

+0

謝謝。奇蹟般有效。幫了我很多。 –

+0

而不是實例化一個新的'SerializerSettings',我建議更新默認值(只需按照您在'WebApiConfig.cs'中的方式訪問它)。這樣你就不會失去其他默認的串行器設置。 –

0

爲什麼使用接口類型的方法?看起來像Web API,不知道應該使用什麼樣的實例來實現消息參數。似乎必須爲此操作編寫自定義模型聯編程序。

+0

謝謝你的回覆。我使用的是接口類型,因爲我需要能夠在一個API調用中發佈不同類型消息的列表。我已經說過,我認爲問題是接口類型沒有被轉換爲具體的類型。你所描述的一個例子是有幫助的。 – mayabelle

+0

首先,您必須發送一些數據,用於在您的請求中指定IMessageApiEntity的具體類型。那麼你應該實現你的IModelBinder([小例子](http://www.dotnetcurry.com/ShowArticle.aspx?ID=584)),並且[ModelBinder(typeof(YourCustomModelBinderTypeName))]的[FromBody]爲您的「消息」方法參數 –

0

幾個星期前,我有一個與.NET Core WebAPI類似的問題。 添加以下線的提出的解決方案並沒有爲我工作:

config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto; 

我結束了創建一個通用的對象,可以把我的IEnumerable,其中T是我的預期類

[Serializable] 
public class GenericListContainer<T> where T : class 
{ 
    #region Constructors 

    public GenericListContainer() 
    { 

    } 

    public GenericListContainer(IEnumerable<T> list) 
    { 
     List = list; 
    } 
    #endregion 

    #region Properties 

    public IEnumerable<T> List { get; set; } 

    #endregion 
} 

然後我改變我的webapi方法爲:

[Route("api/system-users/save-collection-async")] 
[HttpPost] 
[ProducesResponseType(typeof(string), 200)]  
public async Task<IActionResult> SaveSystemUserCollectionAsync([FromBody] GenericListContainer<SystemUser> dto) 
{ 
    var response = await _systemUserService.SaveSystemUserCollectionAsync(dto.List); 
    return Ok(response); 
} 

此方法返回保存的用戶的ID(Guid在我的情況)。

希望這可以幫助別人!

相關問題