C#: Posting Model from body and file as MultipartFormDataContent - c#

I'm looking for a way to send model and image in one request. I tried to send my model from body, but I don't know how to send the file. Is there another way than sending image and model in a different files?
Here's the POST method from my API:
[HttpPost]
[Route("UploadNewEvent")]
public async Task<IActionResult> CreateNewEventAsync([FromBody] EventModel model)
{
var file = this.Request.Form.Files.LastOrDefault();
if (file != null)
{
var uploads = Path.Combine(_environment.WebRootPath, "uploads");
using (var fileStream = new FileStream(Path.Combine(uploads, "test.jpg"), FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
}
// do sth with model later
return Ok();
}
And here's the code from my App:
public async Task SendNewEvent(EventModel model, MediaFile photo)
{
var uri = $"{baseUri}api/User/Event/CreateNewEvent";
if (photo != null)
{
var multipartContent = new MultipartFormDataContent();
multipartContent.Add(new StreamContent(photo.GetStream()), "\"file\"", $"\"{photo.Path}\"");
var httpClient = new HttpClient();
var jsonObject = JsonConvert.SerializeObject(model);
var stringContent = new StringContent(jsonObject, Encoding.UTF8, "application/json");
var httpResponseMessage = await httpClient.PostAsync(uri, stringContent);
}
}

For passing Model with File parameter, you need to post data as form-data.
Follow steps below:
Change FromBody to FromForm
[HttpPost]
[Route("UploadNewEvent")]
public async Task<IActionResult> CreateNewEventAsync([FromForm] EventModel model)
{
// do sth with model later
return Ok();
}
Change client code to send form-data instead of json string
var uri = $"https://localhost:44339/UploadNewEvent";
FileStream fileStream = new FileStream(#"filepath\T1.PNG", FileMode.Open);
var multipartContent = new MultipartFormDataContent();
multipartContent.Add(new StreamContent(fileStream), "\"file\"", #"filepath\T1.PNG");
// EventModel other fields
multipartContent.Add(new StringContent("2"), "Id");
multipartContent.Add(new StringContent("Tom"), "Name");
var httpClient = new HttpClient();
var httpResponseMessage = httpClient.PostAsync(uri, multipartContent).Result;
EventModel
public class EventModel
{
public int Id { get; set; }
public string Name { get; set; }
public IFormFile File { get; set; }
}

I have resolved this type of issue by following code. Please let me know if you find any difficulty. In my example I have used File, Model Object and simple string will help in future.
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace TestingProject
{
class Program1
{
static void Main(string[] args)
{
UploadFile();
}
public static async Task UploadFile()
{
HttpClient httpClient = new HttpClient
{
BaseAddress = new Uri("https://google.com/")
};
var filepath = #"C:\Sample Documents.pdf";
var filename = "Sample Documents.pdf";
using (MultipartFormDataContent content = new MultipartFormDataContent())
{
ByteArrayContent fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes(filepath));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = filename };
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
Request request = new Request()
{
UserId = "1",
UserName = "test",
address = new AddressModel()
{
City = "test",
Country = "India"
},
FileDetails = fileContent
};
var addressSerialize = JsonConvert.SerializeObject(request.address);
FileStream fileStream = new FileStream(filepath, FileMode.Open);
var multipartContent = new MultipartFormDataContent();
multipartContent.Add(new StreamContent(fileStream), "\"file\"", filepath);
multipartContent.Add(new StringContent(request.UserId), "UserId");
multipartContent.Add(new StringContent(request.UserName), "UserName");
multipartContent.Add(new StringContent(addressSerialize), "address");
HttpResponseMessage httpResponseMessage = await httpClient.PostAsync("upload", multipartContent).ConfigureAwait(false);
var personResponse = await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
public class Request
{
/// <summary>
/// userId
/// </summary>
[JsonProperty(PropertyName = "userId")]
public string UserId { get; set; }
/// <summary>
/// UserName
/// </summary>
[JsonProperty(PropertyName = "UserName")]
public string UserName { get; set; }
/// <summary>
/// docType
/// </summary>
[JsonProperty(PropertyName = "FileDetails")]
public ByteArrayContent FileDetails { get; set; }
/// <summary>
/// address
/// </summary>
[JsonProperty(PropertyName = "address")]
public AddressModel address { get; set; }
}
public class AddressModel
{
/// <summary>
/// City
/// </summary>
[JsonProperty(PropertyName = "City")]
public string City { get; set; }
/// <summary>
/// Country
/// </summary>
[JsonProperty(PropertyName = "Country")]
public string Country { get; set; }
}
}
}

Related

I am trying to submit an object that contains some data and a file from the client app to the API app using ASP.CORE 5

I have tried to submit an object from client app to an API which contains some data and a file, but I failed to do so.
Here is the code:
(1) The model:
public class ABC
{
public int Id { get; set; }
public string Image { get; set; }
public string Name { get; set; }
[NotMapped]
public IFormFile File { get; set; }
}
(2) The client app controller
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(ABC aBC)
{
using (var httpClient = new HttpClient())
{
StringContent content = new StringContent(JsonConvert.SerializeObject(aBC), Encoding.UTF8, "application/json");
using (var response = httpClient.PostAsync(BaseURLManager.BaseUrl + "ABCs", content))
{
var apiResponse = response.Result.Content.ReadAsStringAsync();
aBC = JsonConvert.DeserializeObject<ABC>(apiResponse.Result);
}
}
return View(aBC);
}
(3) The API controller
// POST: api/ABCs
[HttpPost]
public async Task<ActionResult<ABC>> PostABC([FromForm] ABC aBC)
{
_context.ABC.Add(aBC);
await _context.SaveChangesAsync();
return CreatedAtAction("GetABC", new { id = aBC.Id }, aBC);
}
Could any one provide me a working code, I am using ASP.NET Core 5.
Thank you in advance
Since you use the FromForm attribute inside the api method, you should send request in formdata instead of json format.
More details, you could refer to below codes:
var client = new HttpClient
{
BaseAddress = new("https://localhost:7105/api/")
};
var path = $"{_hostEnvironment.ContentRootPath}test.json";
var stream = System.IO.File.OpenRead(path);
var request = new HttpRequestMessage(HttpMethod.Post, "PostABC");
var content = new MultipartFormDataContent
{
// file
{ new StreamContent(stream), "File", "test.json" },
// payload
{ new StringContent("1"), "Id" },
{ new StringContent("bbbb"), "Image" },
{ new StringContent("ccc"), "Name" }
};
request.Content = content;
var re = client.SendAsync(request).Result;
Result:

C# HttpClient post content with FormUrlEncodedContent object in Dictionary string/object

I am trying to post a contect to my server.
This is how I have been doing it for the past and it was working until I had to use objects besides strings.
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(authType, tokens);
var postParams = new Dictionary<string, object>();
postParams.Add("string", string);
postParams.Add("int", string);
postParams.Add("datetime", DateTime);
postParams.Add("datetime", DateTime);
postParams.Add("Match", Match);
postParams.Add("TicketId", token);
using (var postContent = new FormUrlEncodedContent(postParams.ToDictionary()))
{
var myContent = JsonConvert.SerializeObject(postParams);
var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (HttpResponseMessage response = await client.PostAsync(#"http://url/api", byteContent))
{
response.EnsureSuccessStatusCode(); // Throw if httpcode is an error
using (HttpContent content = response.Content)
{
string result = await content.ReadAsStringAsync();
var Json = JsonConvert.DeserializeObject<bool>(result);
return Json;
}
}
}
}
And this is how my request is supposed to be.
methode: POST
object: {
"title":"test-ticket-2",
"detail": "Description test create ticket in prod",
"dateStart": "2019-10-06",
"dateEnd": "2019-10-12",
"ratio": "2.15",
"matchResult": "2",
"matchs": [
{
"Teams": "Test-match-1",
"Proposal": "3x",
"DateStart": "2019-10-06 18:00",
"DateEnd": "2019-10-06 20:00",
"Payout": "0.6"
}
]
I have no idea IF and HOW I can add Objects other than string and make the request.
Any ideas?
Edit: Match looks like this
public class Match
{
public int Id { get; set; }
public string Teams { get; set; }
public string MatchResults { get; set; }
public string Proposal { get; set; }
public string Payout { get; set; }
public DateTime? DateStart { get; set; }
public DateTime? DateEnd { get; set; }
public Uri Ball { get; set; }
public int TicketId { get; set; }
}
HOW I can add Objects other than string and make the request. Any
ideas?
using (HttpClient httpclient = new HttpClient())
{
Models.ApplicationUser applicationUser = new ApplicationUser();
string serialized = Newtonsoft.Json.JsonConvert.SerializeObject(applicationUser);
StringContent stringContent = new StringContent(serialized);
httpclient.PostAsync("url", stringContent);
}
Hope you want to do something like this

Azure Function C# - Http Trigger throws System.Web.Extensions could not be found

I am trying to create a C# HTTP-triggered Function from the Azure portal (Embedded Analytics with Power BI). I follow the post of Taygan ( https://www.taygan.co/blog/2018/05/14/embedded-analytics-with-power-bi ) and using the ref for System.Web.Extensions but it throw:
Metadata file 'System.Web.Extensions' could not be found
This is the code:
#r "System.Web.Extensions"
using System.Configuration;
using System.Net;
using System.Text;
using System.Web.Script.Serialization;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.PowerBI.Api.V2;
using Microsoft.PowerBI.Api.V2.Models;
using Microsoft.Rest;
// Static Values
static string authorityUrl = "https://login.windows.net/common/oauth2/authorize/";
static string resourceUrl = "https://analysis.windows.net/powerbi/api";
static string apiUrl = "https://api.powerbi.com/";
static string clientId = ConfigurationManager.AppSettings["PBIE_CLIENT_ID"];
static string username = ConfigurationManager.AppSettings["PBIE_USERNAME"];
static string password = ConfigurationManager.AppSettings["PBIE_PASSWORD"];
static string groupId = ConfigurationManager.AppSettings["PBIE_GROUP_ID"];
static string reportId = ConfigurationManager.AppSettings["PBIE_REPORT_ID"];
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
// Authenticate with Azure Ad > Get Access Token > Get Token Credentials
var credential = new UserPasswordCredential(username, password);
var authenticationContext = new AuthenticationContext(authorityUrl);
var authenticationResult = await authenticationContext.AcquireTokenAsync(resourceUrl, clientId, credential);
string accessToken = authenticationResult.AccessToken;
var tokenCredentials = new TokenCredentials(accessToken, "Bearer");
using (var client = new PowerBIClient(new Uri(apiUrl), tokenCredentials))
{
// Embed URL
Report report = client.Reports.GetReportInGroup(groupId, reportId);
string embedUrl = report.EmbedUrl;
// Embed Token
var generateTokenRequestParameters = new GenerateTokenRequest(accessLevel: "view");
EmbedToken embedToken = client.Reports.GenerateTokenInGroup(groupId, reportId, generateTokenRequestParameters);
// JSON Response
EmbedContent data = new EmbedContent();
data.EmbedToken = embedToken.Token;
data.EmbedUrl = embedUrl;
data.ReportId = reportId;
JavaScriptSerializer js = new JavaScriptSerializer();
string jsonp = "callback(" + js.Serialize(data) + ");";
// Return Response
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(jsonp, Encoding.UTF8, "application/json")
};
}
}
public class EmbedContent
{
public string EmbedToken { get; set; }
public string EmbedUrl { get; set; }
public string ReportId { get; set; }
}
How can I fix it? Please help me, thank you.
Problem is caused by the difference of Function runtime.
The tutorial you follow creates function on ~1 runtime where code targets at .NET Framework , while the one you create is on ~2 runtime which runs on .NET Core env. When we create a new Function app its runtime is set to ~2 by default now.
Solution is to set FUNCTIONS_EXTENSION_VERSION to ~1 in Application settings on portal.
To achieve that in ~2 runtime, create a httptrigger in ~2 and replace the sample code with snippet below. Note you also have to add PBIE_TENANT_ID in Application settings with value get from Azure Active Directory> Properties>Directory ID.
#r "Newtonsoft.Json"
using System.Net;
using System.Text;
using Newtonsoft.Json;
static string resourceUrl = "https://analysis.windows.net/powerbi/api";
static string clientId = Environment.GetEnvironmentVariable("PBIE_CLIENT_ID");
static string username = Environment.GetEnvironmentVariable("PBIE_USERNAME");
static string password = Environment.GetEnvironmentVariable("PBIE_PASSWORD");
static string groupId = Environment.GetEnvironmentVariable("PBIE_GROUP_ID");
static string reportId = Environment.GetEnvironmentVariable("PBIE_REPORT_ID");
static string tenantId = Environment.GetEnvironmentVariable("PBIE_TENANT_ID");
static string tokenEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/token";
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ILogger log)
{
// Get access token
HttpClient authclient = new HttpClient();
log.LogInformation(resourceUrl);
log.LogInformation(tokenEndpoint);
var authContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", username),
new KeyValuePair<string, string>("password", password),
new KeyValuePair<string, string>("client_id", clientId),
new KeyValuePair<string, string>("resource", resourceUrl)
});
var accessToken = await authclient.PostAsync(tokenEndpoint, authContent).ContinueWith<string>((response) =>
{
log.LogInformation(response.Result.StatusCode.ToString());
log.LogInformation(response.Result.ReasonPhrase.ToString());
log.LogInformation(response.Result.Content.ReadAsStringAsync().Result);
AzureAdTokenResponse tokenRes =
JsonConvert.DeserializeObject<AzureAdTokenResponse>(response.Result.Content.ReadAsStringAsync().Result);
return tokenRes?.AccessToken;
});
// Get PowerBi report url and embed token
HttpClient powerBiClient = new HttpClient();
powerBiClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
log.LogInformation(accessToken);
var embedUrl =
await powerBiClient.GetAsync($"https://api.powerbi.com/v1.0/myorg/groups/{groupId}/reports/{reportId}")
.ContinueWith<string>((response) =>
{
log.LogInformation(response.Result.StatusCode.ToString());
log.LogInformation(response.Result.ReasonPhrase.ToString());
PowerBiReport report =
JsonConvert.DeserializeObject<PowerBiReport>(response.Result.Content.ReadAsStringAsync().Result);
return report?.EmbedUrl;
});
var tokenContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("accessLevel", "view")
});
var embedToken = await powerBiClient.PostAsync($"https://api.powerbi.com/v1.0/myorg/groups/{groupId}/reports/{reportId}/GenerateToken", tokenContent)
.ContinueWith<string>((response) =>
{
log.LogInformation(response.Result.StatusCode.ToString());
log.LogInformation(response.Result.ReasonPhrase.ToString());
PowerBiEmbedToken powerBiEmbedToken =
JsonConvert.DeserializeObject<PowerBiEmbedToken>(response.Result.Content.ReadAsStringAsync().Result);
return powerBiEmbedToken?.Token;
});
// JSON Response
EmbedContent data = new EmbedContent
{
EmbedToken = embedToken,
EmbedUrl = embedUrl,
ReportId = reportId
};
string jsonp = "callback(" + JsonConvert.SerializeObject(data) + ");";
// Return Response
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(jsonp, Encoding.UTF8, "application/json")
};
}
public class AzureAdTokenResponse
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
}
public class PowerBiReport
{
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "webUrl")]
public string WebUrl { get; set; }
[JsonProperty(PropertyName = "embedUrl")]
public string EmbedUrl { get; set; }
[JsonProperty(PropertyName = "datasetId")]
public string DatasetId { get; set; }
}
public class PowerBiEmbedToken
{
[JsonProperty(PropertyName = "token")]
public string Token { get; set; }
[JsonProperty(PropertyName = "tokenId")]
public string TokenId { get; set; }
[JsonProperty(PropertyName = "expiration")]
public DateTime? Expiration { get; set; }
}
public class EmbedContent
{
public string EmbedToken { get; set; }
public string EmbedUrl { get; set; }
public string ReportId { get; set; }
}

ASP.Net Web APi C# - GetAsync not returning XML response content

I am calling an external service using GetAsync() and passing parameters in query string. When i check the content in the response, i don't see anything returned, however it returns 200 OK and in fiddler it returns me the XML response correctly. I need the XML response to get de-serialize to an C# object and then further save it to DB.
Things tried:
1) Tried this by adding this setting in global- app_start(), It didn't help
GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
2) Created an object and tried to sent it via GetAysnc, that didn't help either.
public class Request
{
[XmlElement]
public string XML { get; set; }
[XmlElement]
public List<string> ProNumber { get; set; }
}
2) Should i try passing parameters in query string and expect json result? if i add mediatyperformatter to application/json?
Here is my code:
public async Task<HttpResponseMessage> GetData()
{
string requestString = "&xml=Y&PRONumber=82040X,03117X";
string result = "";
string url = #"http://my.yrc.com/dynamic/national/servlet?CONTROLLER=com.rdwy.ec.rextracking.http.controller.PublicTrailerHistoryAPIController";
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
HttpResponseMessage response = await client.GetAsync(url+requestString);
if (response.IsSuccessStatusCode)
{
return response;
}
}
}
catch (Exception ex)
{
result = ex.Message;
}
return null;
}
EDIT:
Shipments scp = null;
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "Shipment";
xRoot.IsNullable = true;
XmlSerializer serializer = new XmlSerializer(typeof(Shipment), xRoot);
using (Stream stream = response.Content.ReadAsStreamAsync().Result)
{
scp = (Shipments)serializer.Deserialize(stream);
}
Model:
public class Shipments
{
[XmlArrayItem(Type = typeof(Shipment))]
public Shipment[] Shipment;
}
public class Shipment
{
[XmlAttribute()]
public int returnCode { get; set; }
.................
..............
Getting error:<SHIPMENTS xmlns=''> was not expected.
Any help on this is much appreciated.
Thanks,
WH
This worked for me -
var client = new HttpClient();
var data = client.GetStringAsync("http://my.yrc.com/dynamic/national/servlet?CONTROLLER=com.rdwy.ec.rextracking.http.controller.PublicTrailerHistoryAPIController&xml=Y&PRONumber=82040X,03117X").Result;
var ser = new XmlSerializer(typeof(Shipments));
var t = (Shipments)ser.Deserialize(new StringReader(data));
public class Shipment
{
public string returnCode { get; set; }
public string returnMessage { get; set; }
public string freightBillNumber { get; set; }
//props
}
[XmlRoot(ElementName = "SHIPMENTS")]
public class Shipments
{
[XmlElement(ElementName = "SHIPMENT")]
public List<Shipment> SHIPMENT { get; set; }
}
EDIT
this works as well -
var data = client.GetStreamAsync("http://my.yrc.com/dynamic/national/servlet?CONTROLLER=com.rdwy.ec.rextracking.http.controller.PublicTrailerHistoryAPIController&xml=Y&PRONumber=82040X,03117X").Result;
EDIT
works as well -
var client = new HttpClient();
var data = client.GetAsync("http://my.yrc.com/dynamic/national/servlet?CONTROLLER=com.rdwy.ec.rextracking.http.controller.PublicTrailerHistoryAPIController&xml=Y&PRONumber=82040X,03117X").Result;
var ser = new XmlSerializer(typeof(Shipments));
var t = (Shipments)ser.Deserialize(data.Content.ReadAsStreamAsync().Result);

HttpClient Multipart Form Post in C#

I'm trying to do a multipart form post using the HttpClient in C# and am finding the following code does not work.
Important:
var jsonToSend = JsonConvert.SerializeObject(json, Formatting.None, new IsoDateTimeConverter());
var multipart = new MultipartFormDataContent();
var body = new StringContent(jsonToSend, Encoding.UTF8, "application/json");
multipart.Add(body);
multipart.Add(new ByteArrayContent(File.ReadAllBytes("test.txt")), "test", "test.txt");
var httpClient = new HttpClient();
var response = httpClient.PostAsync(new Uri("http://localhost:55530"), multipart).Result;
Full Program :
namespace CourierMvc.Worker
{
class Program
{
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("Hit any key to make request.");
Console.ReadKey();
try
{
var request = new RestRequest(Method.POST)
{
Resource = "http://localhost:55530"
};
var json = new CourierMessage
{
Id = Guid.NewGuid().ToString(),
Key = "awesome",
From = "khalid#home.com",
To = new[] { "me#test.com", "you#test.com" },
Subject = "test",
Body = "body",
Processed = DateTimeOffset.UtcNow,
Received = DateTime.Now,
Created = DateTime.Now,
Sent = DateTime.Now,
Links = new[] { new Anchor { Link = "http://google.com" }, new Anchor { Link = "http://yahoo.com" } }
};
var jsonToSend = JsonConvert.SerializeObject(json, Formatting.None, new IsoDateTimeConverter());
var multipart = new MultipartFormDataContent();
var body = new StringContent(jsonToSend, Encoding.UTF8, "application/json");
multipart.Add(body);
multipart.Add(new ByteArrayContent(File.ReadAllBytes("test.txt")), "test", "test.txt");
var httpClient = new HttpClient();
var response = httpClient.PostAsync(new Uri("http://localhost:55530"), multipart).Result;
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}
}
I really have no idea why it doesn't work. I get the file to post to the endpoint, but the body (json) never gets there. Am I doing something wrong?
Server Side Code Request:
namespace CourierMvc.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return Content("Home#Index");
}
[ValidateInput(false)]
public ActionResult Create(CourierMessage input)
{
var files = Request.Files;
return Content("OK");
}
}
}
Route Config:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Create", id = UrlParameter.Optional }
);
}
public class CourierMessage
{
public string Id { get; set; }
public string Key { get; set; }
public string From { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public DateTimeOffset Processed { get; set; }
public DateTime Received { get; set; }
public DateTime Created { get; set; }
public DateTime Sent { get; set; }
public HttpPostedFileBase File { get; set; }
}
while (true)
{
Console.WriteLine("Hit any key to make request.");
Console.ReadKey();
using (var client = new HttpClient())
{
using (var multipartFormDataContent = new MultipartFormDataContent())
{
var values = new[]
{
new KeyValuePair<string, string>("Id", Guid.NewGuid().ToString()),
new KeyValuePair<string, string>("Key", "awesome"),
new KeyValuePair<string, string>("From", "khalid#home.com")
//other values
};
foreach (var keyValuePair in values)
{
multipartFormDataContent.Add(new StringContent(keyValuePair.Value),
String.Format("\"{0}\"", keyValuePair.Key));
}
multipartFormDataContent.Add(new ByteArrayContent(File.ReadAllBytes("test.txt")),
'"' + "File" + '"',
'"' + "test.txt" + '"');
var requestUri = "http://localhost:5949";
var result = client.PostAsync(requestUri, multipartFormDataContent).Result;
}
}
}
This is an example of how to post string and file stream with HTTPClient using MultipartFormDataContent. The Content-Disposition and Content-Type need to be specified for each HTTPContent:
Here's my example. Hope it helps:
private static void Upload()
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("User-Agent", "CBS Brightcove API Service");
using (var content = new MultipartFormDataContent())
{
var path = #"C:\B2BAssetRoot\files\596086\596086.1.mp4";
string assetName = Path.GetFileName(path);
var request = new HTTPBrightCoveRequest()
{
Method = "create_video",
Parameters = new Params()
{
CreateMultipleRenditions = "true",
EncodeTo = EncodeTo.Mp4.ToString().ToUpper(),
Token = "x8sLalfXacgn-4CzhTBm7uaCxVAPjvKqTf1oXpwLVYYoCkejZUsYtg..",
Video = new Video()
{
Name = assetName,
ReferenceId = Guid.NewGuid().ToString(),
ShortDescription = assetName
}
}
};
//Content-Disposition: form-data; name="json"
var stringContent = new StringContent(JsonConvert.SerializeObject(request));
stringContent.Headers.Add("Content-Disposition", "form-data; name=\"json\"");
content.Add(stringContent, "json");
FileStream fs = File.OpenRead(path);
var streamContent = new StreamContent(fs);
streamContent.Headers.Add("Content-Type", "application/octet-stream");
streamContent.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\"" + Path.GetFileName(path) + "\"");
content.Add(streamContent, "file", Path.GetFileName(path));
//content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
Task<HttpResponseMessage> message = client.PostAsync("http://api.brightcove.com/services/post", content);
var input = message.Result.Content.ReadAsStringAsync();
Console.WriteLine(input.Result);
Console.Read();
}
}
}
So the problem I'm seeing is that the MultipartFormDataContent request message will always set the content type of the request to "multipart/form-data". Endcoding json and placing that into the request only "looks" like to the model binder as a string.
Your options are:
have your mvc action method receive a string and deserialize into your object
post each property of your model as a form part
create a custom model binder that will handle your request.
Breakup the operation into two posts, first sends the json metadata, the other sends the file. The response from the server should send some id or key to correlate the two requests.
Reading through the RFC document and the MSDN documentation you may be able to do this, if you replace MultipartFormDataContent with MultipartContent. But I have not tested this yet.
string path = #"C:\New folder\Test.pdf"; // **ANY FILE**
var formContent = new MultipartFormDataContent
{
{ new ByteArrayContent(File.ReadAllBytes(path)), "file", Path.GetFileName(path) }
};
var client = new HttpClient();
var response = client.PostAsync(_configuration["Url"], formContent).Result;

Categories