I have 2 MVC sites. One (A) is posting to another (B).
MVC site A:
using (var handler = new WebRequestHandler())
{
handler.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
using (var client = new HttpClient(handler))
{
using (var formData = new MultipartFormDataContent())
{
StreamContent fileStreamContent = new StreamContent();
formData.Add(fileStreamContent, "file", HttpUtility.UrlEncode(Path.GetFileName("some test path")));
var fileReceiveURL = "URL(B)\SomeController\PostFile";
HttpResponseMessage response = client.PostAsync(fileReceiveURL, formData).Result;
if (!response.IsSuccessStatusCode)
{
throw new Exception("Not able to send file to (B). Didn't get a successful response from server.");
}
}
}
}
MVC site B (SomeController):
[HttpPost]
public HttpResponseMessage PostFile(HttpPostedFileBase file)
{
\\ for testing purpose, just return a bad request response code
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
But at (A). the response (breakpoint at [HttpResponseMessage response...] ) is always "StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1" no matter what HttpStatusCode I set to (B) to send back.
How can I send HttpStatusCode between 2 MVC sites?
Instead of checking the response object...
HttpResponseMessage response = client.PostAsync(fileReceiveURL, formData).Result;
response will always return 200 OK.
need to check
HttpResponseMessage response = await client.PostAsync(fileReceiveURL, formData);
string responseString = await response.Content.ReadAsStringAsync();
response.Content contains the proper HttpStatusCode from site B.
Related
I have a REST API which is hosted by my local provider. It has a Plesk panel installed and ModSecurity, which is turned on by default. When I try to make GET request everything works just fine. It gets worse when I try to make POST request.
If I use built-in HttpClient, my request gets rejected by ModSecurity with HTTP502.3 error. The request is made with the following code:
var content = JsonContent.Create(new
{
PatientCode = "123456",
Password = "123456" / auth data
});
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (var httpClientHandler = new HttpClientHandler())
{
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; // mock for invalid SSL
using (var client = new HttpClient(httpClientHandler))
{
var response = await client.PostAsync("https://example.com/post", content);
try
{
var responseString = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<AuthenticationResponse>(responseString);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
What is more interesting, the following code with RestSharp works just fine and I get correct response:
var options = new RestClientOptions("https://example.com/post")
{
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true // mock for invalid SSL
};
var client = new RestClient(options);
var request = new RestRequest()
.AddJsonBody(new
{
PatientCode = "123456",
Password = "123456" // auth data
});
request.AddHeader("Content-Type", "application/json");
var response = await client.PostAsync<AuthenticationResponse>(request);
Also, if I try to make such a request with Postman, it still works fine (Postman generates this HTTP code for my request):
POST /post HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 58
{
"PatientCode":"123456",
"Password":"123456"
}
So what's the matter? Why does ModSecurity blocks POST from HttpClient but doesn't block requests neither from RestSharp nor from Postman?
I'm developing an API who makes searches on a stock photos and now I need to deliver files(Download method) so I created the following code:
public HttpResponseMessage Download(string id)
{
Download download = new Download(id, apiUser);
byte[] myDataBuffer = download.DownloadImage();
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(myDataBuffer);
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
return result;
}
The bytes are received correctly on method DownloadImage(), the problem is in the HttpResponseMessage return, I upload in release website and through another project I have the following code who calls the API:
public static void DownloadNewImage(string id)
{
var request = new RestRequest(Method.GET);
request.Resource = "Home/Download";
request.AddParameter("id", id);
RestResponse response = Execute(request, "website-url");
}
private static RestResponse Execute(RestRequest request, string url)
{
var cliente = new RestClient(url);
cliente.FollowRedirects = false;
var response = cliente.Execute(request);
return (RestResponse)response;
}
When i debug the response, I receive the following:
See that ContentLength = -1 and when i open the Content text the retur is this:
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content:
System.Net.Http.ByteArrayContent, Headers:
{
Content-Type: application/octet-stream
}
I think that is something wrong in the Download method from API who returns HttpResponseMessage, and some parameters is wrong someone can give me help?
I have to call a REST Service from Web API.
Call and retrieve data works well but the return method crash.
I have tried several method that return an async HttpResponseMessage, but I can return this object as well (error socket on chrome ERR_SPDY_PROTOCOL_ERROR).
I've tried too with just a plain json as string, but no more success.
Here some tries :
[Route("{id}")]
public async Task<JObject> Get(string id)
{
dynamic client = new RestClient($"https://...../accounts/{id}/summary",
new Dictionary<string, string> {
//some KVP for access Rest API
});
//await client.Get() returns HttpResponseMessage 200 and Content is well populated
JObject result = JObject.FromObject(await client.Get());
return result;
//Request.CreateResponse(HttpStatusCode.OK, await result.Content.ReadAsAsync<string>());
//HttpResponseMessage result = await client.Get(); => HttpResponseMessage is well filled
//Request.CreateResponse(HttpStatusCode.OK, await result.Content.ReadAsAsync<string>()); => test with wrapping inside a new HttpResponseMessage but no more success
//using (var client = new HttpClient())
//{
// client.BaseAddress = new Uri($"https://....../v1/accounts/{id}/summary");
// client.DefaultRequestHeaders.Accept.Clear();
// client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HttpResponseMessage response = await client.GetAsync("");
// return Request.CreateResponse(HttpStatusCode.OK, response.Content.ReadAsAsync());
//}
}
Is there a simple method to retrieve json from Rest Service and transfer this as it is ?
If these calls are being performed in a Web API, and there is no logic being applied to the JSON Object, then there is little need to parse it before returning it as it will get serialized again when being returned, you can instead parse it on the front-end application and perform your logic there.
HttpClient has a method which returns the response body as a string, this is GetStringAsync. With the body returned as string, you can return that directly in your HttpResponseMessage
Here's an example using your HttpClient commented code.
[Route("{id}")]
public async Task<HttpResponseMessage> Get(string id)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri($"https://....../v1/accounts/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Fetch the response body as a string
// Resource URI added below
string responseContent = await client.GetStringAsync($"{id}/summary");
// Create our response object and set the content to its StringContent
var response =
new HttpResponseMessage(HttpStatusCode.OK) {Content = new StringContent(responseContent)};
// Return our HttpResponseMessage containing our json text
return response;
}
}
If you just want to transfer the json response from another API, you can use code like the following in Web API:
[HttpGet]
[Route("v1/test", Name = "test")]
public HttpResponseMessage GetTest()
{
UriBuilder uriBuilder = new UriBuilder($"https://...../...");
var webRequest = (HttpWebRequest)WebRequest.Create(uriBuilder.Uri);
webRequest.Method = "GET";
webRequest.ContentType = "application/json; charset=utf-8";
webRequest.Accept = "application/json, text/javascript, */*";
using (var jsonResponse = (HttpWebResponse) webRequest.GetResponse())
{
var jsonStream = jsonResponse.GetResponseStream();
MemoryStream ms = new MemoryStream();
jsonStream.CopyTo(ms);
ms.Position = 0;
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(ms);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
return response;
}
}
When the only thing needed is to support authentication or authorization features, i would prefer to use an API manager and not maintain this kind of code myself.
I am with a problem. I have 2 WebApi´s . The webapi2 get the data from DB and return the IMAGE. Here, its ok and working. If i try on browser, show me the image or if i change, the byte array.
The problem is with the Webapi1 that calls this webapi2. I always receive the HttpResponseMessage with false for IsSuccessStatusCode. The error is 500 internal server error.
I am a newbie and i don´t know what to do...i already tryed a lot of things
public async Task<HttpResponseMessage> GetFoto(string exemplo, string exemple2)
{
HttpClientHandler handler = new HttpClientHandler()
{
UseDefaultCredentials = true,
};
using (var client = new HttpClient(handler))
{
client.BaseAddress = new Uri("http://192.111.56.1:1762/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("api/Tr/Test?exemplo="+exemplo+"&pk="+pk+"");
if (response.IsSuccessStatusCode)
{
var data = response.Content.ReadAsByteArrayAsync().Result;
var stream = new MemoryStream(data);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
return response;
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
return null;
}
}
}
My webapi that Works and return me a Image:
//connections code that doesn´t matter....
try
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new MemoryStream(imgBytes);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
return result;
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.Gone);
}
The error is because when you pass a value on the browser, they change some carachters... So, you are passing 2 values... you have to use
On the webapi 1
var MIRACLE = Uri.EscapeDataString(exemplo);
And at the webapi2
var MIRACLE2 = Uri.UnescapeDataString(MIRACLE)
As per your code, the web api 1 will accept only the media type = "application/json".
This is because you have added the below code :
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
So either you remove the line of code or change it to "image/jpeg" from "application/json".
We are using asp.net web api odata entitysetcontroller to get user profiles. The url that represents a single user profile looks like this
http://www.domain.com/api/org/staff(123)
Now bussiness asked us to provide user image as part of the user profile. So I added a odata action method to the exisitng controller.
var staff = builder.EntitySet<Contact>("staff"); //regiester controller
var staffAction = staff.EntityType.Action("picture"); //register action method
staffAction.Returns<System.Net.Http.HttpResponseMessage>();
The odata action method in controller as below
[HttpPost]
public HttpResponseMessage Picture([FromODataUri] int key)
{
var folderName = "App_Data/Koala.jpg";
string path = System.Web.HttpContext.Current.Server.MapPath("~/" + folderName);
using (FileStream mem = new FileStream(path,FileMode.Open))
{
StreamContent sc = new StreamContent(mem);
HttpResponseMessage response = new HttpResponseMessage();
response.Content = sc;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
response.Content.Headers.ContentLength = mem.Length;
response.StatusCode = HttpStatusCode.OK;
return response;
}
}
I tried the following url to test and the method executed successfully. However the problem is that I always recieve the error message with status 504 as a final response.
http://www.domain.com/api/org/staff(123)/picture
"ReadResponse() failed: The server did not return a response for this request."
I think the problem is with closing the FileStream.
Do not close the stream as Web API's hosting layers take care of closing it. Also, you need
not set the content-length explicitly.StreamContent sets this for you.
[HttpPost]
public HttpResponseMessage Picture([FromODataUri] int key)
{
var folderName = "App_Data/Koala.jpg";
string path = System.Web.HttpContext.Current.Server.MapPath("~/" + folderName);
StreamContent sc = new StreamContent(new FileStream(path,FileMode.OpenRead));
HttpResponseMessage response = new HttpResponseMessage();
response.Content = sc;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
response.StatusCode = HttpStatusCode.OK;
return response;
}