get value from formdata from MultipartDataStream not working - asp.net-mvc

POST http://myserver.com/QCCSvcHost/MIME/RealtimeTrans/ HTTP/1.1
Content-Type: multipart/form-data; boundary="XbCY" Host: na-w-lxu3
Content-Length: 1470 Expect: 100-continue Connection: Keep-Alive
--XbCY Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=PayloadType
X12_270_Request_005010X279A1
--XbCY Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=ProcessingMode
RealTime
--XbCY Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=PayloadID
e51d4fae-7dec-11d0-a765-00a0c91e6fa6
My below code only gives name in the above case name = "payloadID" but I don't get value which must be "e51d4fae-7dec-11d0-a765-00a0c91e6fa6"
My code:
var provider = await Request.Content.ReadAsMultipartAsync<MemoryStreamDataProvider>(new MemoryStreamDataProvider());
//access form data
NameValueCollection formData = provider.FormData;
//access files
IList<HttpContent> files = provider.Files;
//Example: reading a file's stream like below
HttpContent file1 = files[0];
Stream file1Stream = await file1.ReadAsStreamAsync();
The formData has array of name payloadID, realtime etc but not the value.

Related

Send MultiValueMap as MultiPartFormData in Feign Client

I am trying to convert the below kotlin code from RestTemplate to Feign client. The rest template code sends multiValueMap as request with content-type header multipart/form-data and consumes JSON object as response.
RestTemplate Code:
var headers = HttpHeaders()
headers.contentType = MediaType.MULTIPART_FORM_DATA
headers.add("custom-header", "value")
val body: MultiValueMap<String, Any> = LinkedMultiValueMap()
body.add("field1", "value1")
body.add("field2", "value2")
val requestEntity = HttpEntity(body, headers)
return restTemplate.postForEntity("https://enmf7tx8y37x.x.pipedream.net/", requestEntity, Object::class.java)
In this case the request is sent as below:
Headers:
Host: enmf7tx8y37x.x.pipedream.net
X-Amzn-Trace-Id: Root=1-6303ecb2-19a833a044ab3bf83f74f256
Content-Length: 342
Accept: application/xml, text/xml, application/json, application/*+xml, application/*+json
Content-Type: multipart/form-data;boundary=_MtEGFIF4XK_aOU8QsXstQuCliV1-llj
custom-header: value
X-B3-TraceId: a67561ec329f9a16
X-B3-SpanId: a6cc94e403bfe318
X-B3-ParentSpanId: a67561ec329f9a16
X-B3-Sampled: 1
User-Agent: Apache-HttpClient/4.5.13 (Java/17.0.3)
Accept-Encoding: gzip,deflate
Body:
--_MtEGFIF4XK_aOU8QsXstQuCliV1-llj
Content-Disposition: form-data; name="field1"
Content-Type: text/plain;charset=UTF-8
Content-Length: 6
value1
--_MtEGFIF4XK_aOU8QsXstQuCliV1-llj
Content-Disposition: form-data; name="field2"
Content-Type: text/plain;charset=UTF-8
Content-Length: 6
value2
--_MtEGFIF4XK_aOU8QsXstQuCliV1-llj--
I tried to do the same in Feign client:
code:
/*val headers = HttpHeaders()
headers.contentType = MediaType.MULTIPART_FORM_DATA
headers.add("custom-header", "value")*/
val body: MultiValueMap<String, Any> = LinkedMultiValueMap()
body.add("field1", "value1")
body.add("field2", "value2")
val result = testClient.test("value", body)
Feign Client:
#FeignClient(
value = "testClient",
url = "https://enmf7tx8y37x.x.pipedream.net/"
)
interface TestClient {
#PostMapping(
consumes = [MediaType.MULTIPART_FORM_DATA_VALUE],
produces = [MediaType.APPLICATION_JSON_VALUE]
)
fun test(
#RequestHeader(value = "custom-header") customHeader: String,
#RequestPart("request") request: MultiValueMap<String, Any>
): ResponseEntity<Object>
}
The header are fine but no value present in the body.
Header:
Host: enmf7tx8y37x.x.pipedream.net
X-Amzn-Trace-Id: Root=1-6303ef0f-78c869881a5b27d0707eab9e
Content-Length: 17
Accept: application/json
Authorization: Basic aHlwb2xhYjp0ZXN0c211cmY=
Content-Type: multipart/form-data; charset=UTF-8; boundary=182c75dd399
custom-header: value
X-B3-TraceId: 2989eb4f12e3d417
X-B3-SpanId: 23414bcdf365784c
X-B3-ParentSpanId: 2989eb4f12e3d417
X-B3-Sampled: 1
User-Agent: Java/17.0.3
Body:
--182c75dd399--
I had to add consumes value as multipart/form-data instead of json to get the right header values for Accept and Content-Type.
How can I populate the request using Feign client? If the #RequestPart is String then the value is sent in the body but any other data type like multiValueMap, byteArray, etc were not working
In feign client you cannot use MultiValueMap directly. You have to use MultipartFile datatype for bytearray and for the remaining metadata fields you need to mention each one as a separate argument in the method. Then FeignClient will generate the same request like the one you showed when using RestTemplate.
import org.springframework.cloud.openfeign.FeignClient
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RequestPart
import org.springframework.web.multipart.MultipartFile
#FeignClient(
value = "testClient",
url = "https://enmf7tx8y37x.x.pipedream.net/"
)
interface TestClient {
#PostMapping(
consumes = [MediaType.MULTIPART_FORM_DATA_VALUE],
produces = [MediaType.APPLICATION_JSON_VALUE]
)
fun test(
#RequestHeader(value = "custom-header") customHeader: String,
#RequestPart(name = "file") file: MultipartFile,
#RequestPart(name = "field1") field1: String
): ResponseEntity<Object>
}
code sample for How to create MultiPartFile:
import org.springframework.mock.web.MockMultipartFile
//val multipartFile: MultipartFile = MockMultipartFile("filename", byteArray)
val multipartFile: MultipartFile = MockMultipartFile("filename", "filename", "content type like application/pdf", byteArray)

C# reading OData $batch multipart/mixed response to a meaningful object(s)

I am consuming an OData Service, I am successfully POSTing my request (using RestSharp) to /$batch endpoint and getting the response. the response header contains
"Content-Type" : "multipart/mixed; boundary=<GUID>"
Body is
--C4254E82B51CFE5BD04201606B9AB7C50
Content-Type: multipart/mixed; boundary=C4254E82B51CFE5BD04201606B9AB7C51
Content-Length: 2221
--C4254E82B51CFE5BD04201606B9AB7C51
Content-Type: application/http; charset=utf-8
Content-Length: 2037
content-transfer-encoding: binary
HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 1732
location: https://test.api/Event/CarEntries('4003581738')
dataserviceversion: 2.0
etag: W/"datetimeoffset'2021-04-21T00%3A49%3A45Z'"
{ JSON }
--C4254E82B51CFE5BD04201606B9AB7C51--
--C4254E82B51CFE5BD04201606B9AB7C50
Content-Type: application/http; charset=utf-8
Content-Length: 15116
content-transfer-encoding: binary
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 15017
dataserviceversion: 2.0
{ JSON }
--C4254E82B51CFE5BD04201606B9AB7C50--
How do I deserialise and extract the JSON Objects in my C# code? I do not want to invent a Regex pattern (well that is my last resort)
I did try using "Simple.OData.Client" (also a few others) but my request is not 100% compatible with the "Simple.OData.Client".
Also tried extracting using the below code but not necessary give me what I want
var sc = new StringContent(response.Content);
var content = sc.ReadAsStreamAsync().Result;
var streamContent = new StreamContent(content);
streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(response.ContentType);
var provider = streamContent.ReadAsMultipartAsync().Result;
Can someone giveme the best way to extract the Json objects ?
Thanks
Nero
I manage to get this working HttpClient and System.Net.Http.Formatting.Extension
Below is the code
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://service-url/Entity/v1.3/$batch"))
{
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Client-Id", "XXXXXXXXX");
// Add all the headers here
// this is your custom batch request
request.Content = new StringContent("--batch\ncontent-type: multipart/mixed;boundary=changeset\n\n--changeset\ncontent-type: application/http\nContent-Transfer-Encoding: binary\n\nPOST CarEntries HTTP/1.1\ncontent-type: application/json;charset=utf-8\naccept: application/json;\n\n{\n\"RefId\": \"Test\",\n\"Child\": {\n\"ChildId\": \"412000415\"\n}\n}\n--changeset--\n--batch--");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/mixed;boundary=batch"); // This is imporatnt - but please refer to your api documentation
var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var multiPartContent = await response.Content.ReadAsMultipartAsync(); // This is part of the extension
var mixedContent = multiPartContent.Contents.First(); // you will have multiple contents, select the content you want
var data = await mixedContent.ReadAsStringAsync();// read it as string
Regex rg = new Regex(#"\{(.|\s)*\}"); // find the json object from mixed content
var json = rg.Match(data);
return JsonConvert.DeserializeObject<TMessage>(json.Value);
}
}
Hope this helps someone in the future. But still, my goal is to use "Simple.OData.Client" or "Microsoft.OData.Client"

MVC 4 WebRequest WebResponse caching

I am trying to disable the caching on on the the pages. The reason - the page in question should display up to date data on each request and the data is coming from external XML feed.
I am using standard HttpWebRequest HttpWebResponse. All is working fine but I am getting some (I believe) caching issues where by querying XML feed URL directly I am getting more up to date data compared to my Controller/View data which uses the same URL.
XML feed URL is appended with random numbers on each request and Caching was disabled in the controller ([OutputCache(NoStore = true, Duration = 0)]) as well as in the ActionResult, which produces the following:
Response
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNetMvc-Version: 5.1
X-AspNet-Version: 4.0.30319
X-Frame-Options: SAMEORIGIN
X-Powered-By: ASP.NET
X-UA-Compatible: IE=edge
Date: Thu, 04 Aug 2016 13:22:33 GMT
Content-Length: 75285
Request
pretty print
GET /investor-relations/share-price HTTP/1.1
Host: cms.crestnicholson-dev.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: ecos.dt=1470316952533; ASP.NET_SessionId=5lbh4v20kac0boadibjfwedr; IsAgreeToCookiePolicy=true
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
And still outdated/cached data is rendered on the pageā€¦
If someone has any ideas/suggestions, It would be greatly appreciated.
Controller code:
[OutputCache(NoStore = true, Duration = 0)]
public class InvestorRelationsController : Controller
{
public ActionResult SharePrice()
{
Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
Response.Cache.SetValidUntilExpires(false);
Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
return PartialView(GetSharePrice());
}
private SharePriceModel GetSharePrice()
{
try
{
var xml = GetSharePriceXml();
return ParseSharePrice(xml);
}
catch (Exception)
{
return new SharePriceModel() {IsServiceUnavailable = true};
}
}
private SharePriceModel ParseSharePrice(string xml)
{
Guard.ArgumentNotNull(xml, "xml");
var model = new SharePriceModel();
var doc = new XmlDocument();
doc.Load(new StringReader(xml));
var root = doc.DocumentElement;
model.DateLastUpdated = root.SelectSingleNode("Time").InnerText;
model.Price = root.SelectSingleNode("CurrentPrice").InnerText;
model.Change = root.SelectSingleNode("Change").InnerText;
model.ChangePersentage = root.SelectSingleNode("PercentageChange").InnerText;
return model;
}
private string GetSharePriceXml()
{
Uri address = new Uri(SiteConfiguration.SharePriceFeedUrl);
Random random = new Random();
string url = address + "?random=" + random.Next();
// Set a default policy level for the "http:" and "https" schemes.
HttpRequestCachePolicy policy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Default);
HttpWebRequest.DefaultCachePolicy = policy;
HttpRequestCachePolicy noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
// Create the web request
var request = WebRequest.Create(url) as HttpWebRequest;
// Set type to POST
request.CachePolicy = noCachePolicy;
request.KeepAlive = false;
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
request.Headers.Add("Cache-Control", "no-cache");
request.Headers.Add("Cache-Control", "private");
// Get response
using (var response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
using (var reader = new StreamReader(response.GetResponseStream()))
{
// Console application output
return reader.ReadToEnd().Trim();
}
}
}
}

Making a post request to pastebin returns a 302 - Moved Temporarily response

I am doing a simple post using GM_xmlhttpRequest to post some text to pastebin. This is my code
GM_xmlhttpRequest({
method: "POST",
url: "http://pastebin.com/post.php",
data: "api_dev_key=5c3***********************073a&api_option=paste&api_paste_code="+encodeURI(photo_url)+"&api_user_key=5******************************f&api_paste_name=cornered&api_paste_private=2&api_paste_expire_date=1W",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
onload: function(response) {
alert("posted " + response);
}
});
I am getting no response in the script. To check if the post request itself is working, I used http://requestmaker.com/ and it shows that the POST request is returning a 302 response
Request Headers Sent:
POST /post.php HTTP/1.1
Host: pastebin.com
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: 152
Response Headers:
HTTP/1.1 302 Moved Temporarily
Date: Wed, 10 Dec 2014 15:27:20 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: __cfduid=d61fd0544ec1b0c284ba908367557bc7f1418225240; expires=Thu, 10-Dec- 15 15:27:20 GMT; path=/; domain=.pastebin.com; HttpOnly
X-Powered-By: PHP/5.5.5
Set-Cookie: cookie_key=1; expires=Wed, 07-Jan-2015 15:27:20 GMT; Max-Age=2419200; path=/; domain=.pastebin.com
Set-Cookie: realuser=1; expires=Thu, 11-Dec-2014 15:27:20 GMT; Max-Age=86400; path=/
location: /index.php?e=2
Vary: Accept-Encoding
Server: cloudflare-nginx
CF-RAY: 196a7749d5c713e9-LAX
Send your request to http://pastebin.com/api/api_post.php instead of http://pastebin.com/post.php.

Invalidate Oauth token

I am trying to invalidate a token but I get the following exception:
+ Headers {X-AspNetMvc-Version: 3.0
xoauth_problem: parameter_absent
xoauth_parameters_absent: oauth_session_handle&oauth_token
Connection: keep-alive
Content-Length: 165
Cache-Control: private
Content-Type: text/html; charset=utf-8
Date: Thu, 16 Aug 2012 20:03:38 GMT
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
} System.Net.WebHeaderCollection
Here is the code:
Uri url = new Uri("https://XXXYYY/OAuth/InvalidateToken");
string oauthHeader = "OAuth oauth_session_handle="AAA3D&",oauth_token="SDSFSDSDF%3D",oauth_consumer_key="5512CONSUMER",oauth_nonce="0000012145o",oauth_signature="QEESIGN99$",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1345141023",oauth_version="1.0"";
HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(url);
webReq.Method = WebRequestMethods.Http.Get;
webReq.Headers.Add(HttpRequestHeader.Authorization, oauthHeader);
WebResponse response = webReq.GetResponse();
Please note I do have parameters

Resources