How to view content delivered from HttpResponseMessage (ASP.NET MVC Web Api) - asp.net-mvc

I create json object and assign it to a StringContent of my HttpResponseMessage instance. Everything works fine when I call the Web API action, the result is 200, the content-length is how it should be, but how to find the content itself, where is the json? What I get in the browser and in Postman is this:
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
Content-Type: application/json
}
Why is this instead of my json string?
Content: System.Net.Http.StringContent

If what you are trying to achieve is to return a valid JSON response, then this is the way to go in Asp.Net MVC
public ActionResult HttpResponseMessage()
{
var oJSON = new { url = "path_to_file", hash = "aaaaaaaaaaaaaaaaa" };
return Json(oJSON, JsonRequestBehavior.AllowGet);
}
Response headers as seen by Postman:
Cache-Control →private
Content-Length →49
Content-Type →application/json; charset=utf-8
Date →Fri, 26 Oct 2018 13:31:44 GMT
Server →Microsoft-IIS/10.0
X-AspNet-Version →4.0.30319
X-AspNetMvc-Version →5.2
X-Powered-By →ASP.NET
X-SourceFiles →=?UTF-8?B?RTpcRXhhbSA3MCA0ODdcNzA0ODdcTVZDUm91dGVzXEhvbWVcSHR0cFJlc3BvbnNlTWVzc2FnZQ==?=
Response body as seen by Postman
{"url":"path_to_file","hash":"aaaaaaaaaaaaaaaaa"}

Related

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"

Getting a 401 unauthorized error on One Login authentication grant type part 2 request

I am using MVC framework to make POST request to OneLogin API to get JWT. I am getting a 401 unauthorized message back at my PostAsync call in the code below.
Error look like following
StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
Cache-Control: no-store, no-cache
Date: Wed, 17 Jun 2020 04:21:23 GMT
Set-Cookie: ol_oidc_canary_30=false; path=/; domain=.onelogin.com
X-Powered-By: Express
Content-Length: 77
Content-Type: application/json; charset=utf-8
}
Am i missing any parameters. I registered my localhost on One login dev account. Is there any setting there i need to update or change?
public async Task<OidcTokenResponse> ProcessToken(string code, string clientSec)
{
string authorityToken = OneLoginAuthorityToken;
var formData = new System.Net.Http.FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("client_id", OneLoginClientID),
new KeyValuePair<string, string>("client_secret", clientSec),
new KeyValuePair<string, string>("grant_type", "authorization_code"),
});
using (var client = new System.Net.Http.HttpClient())
{
const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const System.Net.SecurityProtocolType Tls12 = (System.Net.SecurityProtocolType)_Tls12;
System.Net.ServicePointManager.SecurityProtocol = Tls12;
var res = await client.PostAsync(authorityToken, formData);
var json = await res.Content.ReadAsStringAsync();
var tokenReponse = Newtonsoft.Json.JsonConvert.DeserializeObject<OidcTokenResponse>(json);
return tokenReponse;
}
}
You need to send the redirect_uri again in this message - it is a security feature of the authorization code flow.
Also worth tracing the messages with a tool such as Fiddler to ensure that the messages sent over the wire are what you'd expect.
See steps 4 and 8 of my messages write up for something to compare against.

Odata Controller: Content () method behaving unexpected when pass C# object entity as input

I am trying to pass an C# object in Odatacontroler Content method:
var resp = Content(HttpStatusCode.OK, vResult );
Where vResult is a C# object with two fields (List Messaages; bool IsValidEntity) .
At client when I tried getting response bellow unexpected response coming:
Id = 0x00000003, Status = RanToCompletion, Method = "{null}", Result =
"StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content:
System.Net.Http.StringContent, Headers:\r\n{\r\n Pragma: no-cache\r\n
Cache-Control: no-cache\r\n Date: Wed, 06 Jan 2016 07:04:25 GMT\r\n
Server: Microsoft-IIS/7.5\r\n X-AspNet-Version: 4.0.30319\r\n
X-Powered-By: ASP.NET\r\n Content-Type: application/json;
odata.metadata=minimal\r\n Content-Length: 97\r\n}"
For details below can be referenced:
Odata Controller: How to convert Odata response to C# object at client

Why the browser can't show an EPPlus spreadsheet?

I'm trying a lot of options with complete unsuccess. My need is create a spreadsheed in the server and the user gets it in the browser in a asp.net MVC 5 environment.
In the server the code is:
[HttpPost]
public ActionResult ExportToExcel([ModelBinder(typeof(DevExpressEditorsBinder))] Reports data)
{
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("Sample1");
ws.Cells["A1"].Value = "Sample 1";
ws.Cells["A1"].Style.Font.Bold = true;
var shape = ws.Drawings.AddShape("Shape1", eShapeStyle.Rect);
shape.SetPosition(50, 200);
shape.SetSize(200, 100);
shape.Text = "Sample 1 text text text";
if (data.PDFFileName == null) data.PDFFileName = "Spreadsheet.xlsx";
data.PDFFileName = Path.GetFileNameWithoutExtension(data.PDFFileName) + ".xlsx";
FileContentResult result = new FileContentResult(pck.GetAsByteArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
result.FileDownloadName = data.PDFFileName;
return result;
}
The view is
#Ajax.ActionLink("Created Spreadsheet", "ExportToExcel", "GraphReport", null, new AjaxOptions { HttpMethod = "POST" }, new { #class="btn btn-warning" })
The result in Chrome is:
Remote Address:[::1]:49711
Request URL:http://localhost:49711/GraphReport/ExportToExcel
Request Method:POST
Status Code:200 OK
Response Headers
Cache-Control:private, s-maxage=0
Content-Disposition:attachment; filename=Spreadsheet.xlsx
Content-Length:3561
Content-Type:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Date:Mon, 29 Jun 2015 22:54:38 GMT
Server:Microsoft-IIS/8.0
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:5.2
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcVXNlcnNcbWNhc3Ryb1xEb2N1bWVudHNcVmlzdWFsIFN0dWRpbyAyMDEzXFByb2plY3RzXE1jU29mdFxDVlNcQmVlaGl2ZU1WQ1xHcmFwaFJlcG9ydFxFeHBvcnRUb0V4Y2Vs?=
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Content-Length:31
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
The code is there in response:
PKÓÝFCjkh'¬[Content_Types].xmlµÛN!_eíYh½0ÆtÛjb}f»¤ÂÐþ½,[ij¢I{5?3ß?f½5Õ#iï6åV¡^i·jØûò©¾e%p
wØ°-æ³eª\ë¨a]JáNZ ´>ZHyW"\Ã
Why it is not being interpreted as download attached file?
It's because you cannot download file via AJAX call.
Solution: Create a form, use the POST method, submit the form. When the server page responds to the request, write a response header for the mime type of the file, and it will present a download dialog. You may need to use an iframe to prevent your site from navigating to error page if server returns an error.
Many of questions like this, they all have answers..
Ajax call to download file returned from RESTful service
Handle file download from ajax post

dotnetopenauth twitter api 1.1 signed request

I stuсk on using DNOA library for twitter 1.1 api
enter code here
I am trying to call users/show.json api
protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response)
{
string accessToken = response.AccessToken;
string str2 = response.ExtraData["user_id"];
string userName = response.ExtraData["screen_name"];
Uri location = new Uri("https://api.twitter.com/1.1/users/show.json?user_id=" + str2);
MessageReceivingEndpoint profileEndpoint = new MessageReceivingEndpoint(location, HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
HttpWebRequest request = base.WebWorker.PrepareAuthorizedRequest(profileEndpoint, accessToken);
Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary.Add("accesstoken", accessToken);
try
{
using (WebResponse wresponse = request.GetResponse())
{
var str = Utilities.ProcessResponse(wresponse);
var json = JObject.Parse(str);
dictionary.AddNotEmpty("name", json.Value<string>("name"));
dictionary.AddNotEmpty("location", json.Value<string>("location"));
dictionary.AddNotEmpty("description", json.Value<string>("description"));
dictionary.AddNotEmpty("url", json.Value<string>("url"));
}
}
catch (Exception)
{
}
return new AuthenticationResult(true, base.ProviderName, str2, userName, dictionary);
}
This what is sends to twitter
GET https://api.twitter.com/1.1/users/show.json?user_id=2193937074 HTTP/1.1
Authorization: OAuth oauth_token="2193937074-cgmZbmJIIb75f7MkQgbdjuvQaen2xzM1WFXXC7G",oauth_consumer_key="XVCgN3fkwzTGgeSm1FBa1Q",oauth_nonce="93UjjRkP",oauth_signature_method="HMAC-SHA1",oauth_signature="YzfXzU3VeEI9xl2SfuknPB33%2FiM%3D",oauth_version="1.0",oauth_timestamp="1389265955"
Host: api.twitter.com
The responce is
HTTP/1.1 401 Unauthorized
content-length: 63
content-type: application/json; charset=utf-8
date: Thu, 09 Jan 2014 11:12:36 UTC
server: tfe
set-cookie: guest_id=v1%3A138926595613849064; Domain=.twitter.com; Path=/; Expires=Sat, 09-Jan-2016 11:12:36 UTC
strict-transport-security: max-age=631138519
{"errors":[{"message":"Could not authenticate you","code":32}]}
The dev.twitter's OAuth tool shows the valid sample of signed header:
GET https://api.twitter.com/1.1/users/show.json?user_id=2193937074 HTTP/1.1
Authorization: OAuth oauth_consumer_key="XVCgN3fkwzTGgeSm1FBa1Q", oauth_nonce="dbf6f6c1aa6dc226de25265da3d63167", oauth_signature="K3Qfyc9qANFgckQNyqsaDWCnh%2BY%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1389266681", oauth_token="2193937074-cgmZbmJIIb75f7MkQgbdjuvQaen2xzM1WFXXC7G", oauth_version="1.0"
Host: api.twitter.com
It loook's like the main difference is in length of the oauth_nonce?
DNOA - oauth_nonce="93UjjRkP"
OAuth tool - oauth_nonce="dbf6f6c1aa6dc226de25265da3d63167"
I solved the problem.
The main problem is how the signature is created, the TokenSecret is excluded from it's forming. The core of the this behavior is the AuthenticationOnlyCookieOAuthTokenManager manager that is used inside the base DotNetOpenAuth.AspNet.Clients.TwitterClient class.
public class AuthenticationOnlyCookieOAuthTokenManager : IOAuthTokenManager
{
...
public virtual void ReplaceRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret)
{
HttpCookie cookie = new HttpCookie("OAuthTokenSecret") {
Value = string.Empty, //<<< now it's empty
Expires = DateTime.UtcNow.AddDays(-5.0)
};
this.Context.Response.Cookies.Set(cookie);
}
...
}
It's just remove the tokenSecret;
The solution is to use the DotNetOpenAuth.AspNet.Clients.InMemoryOAuthTokenManager class. So you need just derive from OAuthClient and implement proper constructor:
public class TwitterClient : DotNetOpenAuth.AspNet.Clients.OAuthClient
{
protected TwitterClient(string appKey, string appSecret) :
base ("twitter",
new DotNetOpenAuthWebConsumer(
TwitterServiceDescription,
new InMemoryOAuthTokenManager(appKey, appSecret)))
{ }
...
}
Also have found the familiar post Custom OAuth client in MVC4 / DotNetOpenAuth - missing access token secret

Resources