'Call Webapi with Dictionary<String, object> as parameter from ASP .NET MVC Application
I have a WebApi defined as below
public ActionResult DoSomeAction([FromForm(Name = "file")] IFormFile dataFile,
Dictionary<string,object> collection)
{
//do something
}
I am trying to call this from my client as shown below,
using (var client = new HttpClient())
{
var api_Uri = Environment.GetEnvironmentVariable("API_URL");
client.BaseAddress = new Uri(api_Uri);
client.DefaultRequestHeaders.Clear();
//Define request data format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Dictionary<string, object> data = new Dictionary<string, object>();
data.Add("a", "sasas");
data.Add("b", "sasas");
data.Add("", "sasas");
var inputSerialized = JsonSerializer.Serialize(data);
var stringContent = new StringContent(inputSerialized , Encoding.UTF8, "application/json");
var requestString = string.Format("api/DoSomeAction?selectedRule={0}", stringContent);
HttpResponseMessage Res = await client.PostAsync(requestString, multipartContent);
}
multipartContent is MultipartFormDataContent which contains File information. The above code is not working. Some guidance would be appreciated.
Solution 1:[1]
I was able to solve this my implementing a custom IModelBinder. I moved IFormFile and Dictionary to a class. While creating the request as below ,
internal MultipartFormDataContent GetRequestParams(IFormFile FilePath)
{
MultipartFormDataContent multipartContent = GetFileContent(FilePath);
var dataExtractor = new DataExtractor();
var dictionaryData = dataExtractor.GetDictionary(); //This return Dictionary<string,object>
var serialisedData = JsonSerializer.Serialize(dictionaryData);
var stringContent = new StringContent(serialisedData, Encoding.UTF8, "application/json");
multipartContent.Add(stringContent, "MyCollection");
return multipartContent;
}
private MultipartFormDataContent GetFileContent(IFormFile FilePath)
{
byte[] data;
using (var br = new BinaryReader(FilePath.OpenReadStream()))
{
data = br.ReadBytes((int) FilePath.OpenReadStream().Length);
}
ByteArrayContent bytes = new ByteArrayContent(data);
MultipartFormDataContent multiContent = new MultipartFormDataContent();
multiContent.Add(bytes, "File", FilePath.FileName);
//Key is "File", bcos my property name in class is File. This should match
return multiContent;
}
Custom class containing the data
public class Input
{
public IFormFile File { get; set; }
[ModelBinder(BinderType = typeof(FormDataJsonBinder))]
public Dictionary<string,object> MyCollection{ get; set; }
}
Custom IModelBinder implementation
public class FormDataJsonBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var modelName = bindingContext.ModelName;
var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
if (valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
bindingContext.ModelState.SetModelValue(modelName, valueProviderResult);
var value = valueProviderResult.FirstValue;
if (string.IsNullOrEmpty(value))
{
return Task.CompletedTask;
}
try
{
var result = JsonSerializer.Deserialize(value, bindingContext.ModelType);
bindingContext.Result = ModelBindingResult.Success(result);
}
catch (Exception ex)
{
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}
}
Web Api Signature
public IActionResult ExecuteRule([FromForm] Input inputdata)
{
// Do something
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | harin04 |
