404 error at API while logging the app from simulator - asp.net

I have created the simple login page in xamarin.forms,i have API for those logins,while running at postman iam getting the output,but while logging from the simulator iam getting the following error.
{StatusCode: 404, ReasonPhrase: 'Not Found', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Cache-Control: private
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=639506ba4afdd530b4429c0d57e89977accb4b666a1e17dbe3fcc5c1fce369d5;Path=/;HttpOnly;Domain=snovahub.azurewebsites.net
Date: Wed, 13 Sep 2017 13:23:00 GMT
Content-Length: 3485
Content-Type: text/html; charset=utf-8
}}
My Api method is as follows:
#region Get results from api
public static async Task<T> GetResultFromApi<T>(string serviceUrl,bool isTrue=true)
{
try
{
GetConnection();
var response = await _httpClient.GetAsync(new Uri(SnovaHubApiUrls.SnovaHubWebUrl + serviceUrl));
var stringAsync = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var responseJson = stringAsync;
return JsonConvert.DeserializeObject<T>(responseJson);
}
LoggingManager.Error("Received error response: " + stringAsync);
return default(T);
}
catch (Exception exception)
{
LoggingManager.Error(exception);
return default(T);
}
}
#endregion

The issue is that you are setting the HttpClient.BaseAddress and then also passing in a full URL when calling HttpClient.GetAsync(). You need to choose one or the other. So:
Option 1:
private static void GetConnection() {
if (_httpClient == null) {
_httpClient = new HttpClient { BaseAddress = new Uri(SnovaHubApiUrls.SnovaHubWebUrl) }; //You MUST place a / (slash) at the end of your BaseAddress ("http://something.com/api/" for example)
}
}
Then in your GetResultFromApi() method:
...
var response = await _httpClient.GetAsync(serviceUrl); //You MUST NOT place a slash at the beginning of 'serviceUrl' when using BaseAddress
Option 2:
private static void GetConnection() {
if (_httpClient == null) {
_httpClient = new HttpClient(); //Removed BaseAddress
}
}
Then in your GetResultFromApi() method:
...
var response = await _httpClient.GetAsync(new Uri(SnovaHubApiUrls.SnovaHubWebUrl + serviceUrl)); //Passing full URL

Related

Xamarin forms ASP.NET android emulator cannot access localhost API

I'm developing a Xamarin forms app that uses ASP.NET Web Application template. I followed this tutorial on YouTube. I'm having problem using the PostAsync method. The web api itself can start OK via IIS Chrome on my local machine, but not via the emulator. I printed the response message, displayed as
StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content:
System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
Server: Microsoft-HTTPAPI/2.0
Date: Sun, 26 Sep 2021 06:53:22 GMT
Connection: close
Content-Type: text/html; charset=us-ascii
Content-Length: 334
}
Here's the service class which contains the RegisterAsync method
public class UserService
{
private string androidApiUrl = "https://10.0.2.2:44358/api/Account/Register";
private string iOSApiUrl = "https://localhost:44358/api/Account/Register";
private HttpClient client;
public UserService()
{
var httpClientHandler = new HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback =
(msg, cert, chain, err) => { return true; };
client = new HttpClient(httpClientHandler);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<bool> RegisterAsync(string username, string pswd, string confmPswd)
{
var newAccount = new ModelAccount
{
Email = username,
Password = pswd,
ConfirmPassword = confmPswd
};
var json = JsonConvert.SerializeObject(newAccount);
HttpContent content = new StringContent(json);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json")
{
CharSet = Encoding.UTF8.WebName
};
try
{
var response = await client.PostAsync(androidApiUrl, content);
Console.WriteLine(response.ToString());
Console.WriteLine(response.ReasonPhrase);
Console.WriteLine(response);
return response.IsSuccessStatusCode;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
throw e;
}
}
}
Here's the WebAPI's properties...
Here's the ModelConvert which is json-serialized.
class ModelAccount
{
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
If it makes any different if I changed the port number to 61902 as suggest by this blog, it still won't work.
Thank you
Edit:
as requested by #Aristos, here are the port numbers connected.
On the settings you have define the port number - usually this is a random port so probably have change on your system. Check on witch port your local iis is running when you run visual studio and change that according.

Unable to call Patch method of Web API in ASP.NET Core

My API has a method of type Patch that I need to call from the client. This method is:
[HttpPatch("{id}")]
public StatusCodeResult Patch(int id, [FromBody]JsonPatchDocument<Reservation> patch)
{
Reservation res = Get(id);
if (res != null)
{
patch.ApplyTo(res);
return Ok();
}
return NotFound();
}
I am trying to call it from my client whose code is:
[HttpPost]
public async Task<IActionResult> UpdateReservationPatch(int id, Reservation reservation)
{
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage
{
RequestUri = new Uri("http://localhost:8888/api/Reservation/" + id),
Method = new HttpMethod("Patch"),
Content = new StringContent("[{ \"op\":\"replace\", \"path\":\"Name\", \"value\":\"" + reservation.Name + "\"},{ \"op\":\"replace\", \"path\":\"StartLocation\", \"value\":\"" + reservation.StartLocation + "\"}]", Encoding.UTF8, "application/json")
};
var response = await httpClient.SendAsync(request);
}
return RedirectToAction("Index");
}
I am failing to do so and getting error.
StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Tue, 28 Jul 2020 12:25:24 GMT
Content-Type: application/problem+json; charset=utf-8
Content-Length: 370
}}
What can be the problem?

While accessing Web API getting 404 Not Found

While accessing web Api in xamarin.forms i am getting this error below which is i am unable to Solve
{StatusCode: 404, ReasonPhrase: 'Not Found', Version: 1.1, Content:
System.Net.Http.StreamContent, Headers: { Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET Date: Fri, 09 Feb 2018 12:50:00 GMT
Content-Type: text/html Content-Length: 1245 }}
This is my web Api Code.
public IList<TCourse> GetData()
{
try
{
using (var context = new HCMSEntities())
{
var cli = (from b in context.tblTrainingCourses
orderby b.CourseID
select new TCourse { CourseID = b.CourseID, Course = b.Course }
).ToList();
return cli;
}
}
catch (Exception ex)
{
return null;
}
}
And here is the code which is consuming the api and i am getting above error.
public async Task Index()
{
List<TCourse> EmpInfo = new List<TCourse>();
try
{
using (var client = new HttpClient())
{
//Passing service base url
client.BaseAddress = new Uri("http://10.20.2.62/");
client.DefaultRequestHeaders.Clear();
//Define request data format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Sending request to find web api REST service resource GetAllEmployees using HttpClient
HttpResponseMessage Res = await client.GetAsync("api/Course");
//Checking the response is successful or not which is sent using HttpClient
if (Res.IsSuccessStatusCode)
{
//Storing the response details recieved from web api
var EmpResponse = Res.Content.ReadAsStringAsync().Result;
//Deserializing the response recieved from web api and storing into the Employee list
EmpInfo = JsonConvert.DeserializeObject<List<TCourse>>(EmpResponse);
}
}
}
catch (Exception e)
{
}
}
The web Api is not deployed.I tried http://localhost/ in base address than i switched to Ip.
no idea whats wrong and where.
kindly Guide.

How to Create a Multipart HTTP Response With ASP.NET Core

I would like to create an action method in my ASP.NET Core controller which returns a Multipart HTTP Response containing several files. I know that using a .zip file is the recommended approach for websites but I am considering using such a request for an API.
The examples I have been able to find in the ASP.NET Core samples are to do with multipart HTTP requests when uploading files. In my case, I want to download files.
UPDATE
I've raised the following GitHub issue: #4933
I've written a more generic MultipartResult class which just inherits from ActionResult:
Usage Example
[Route("[controller]")]
public class MultipartController : Controller
{
private readonly IHostingEnvironment hostingEnvironment;
public MultipartController(IHostingEnvironment hostingEnvironment)
{
this.hostingEnvironment = hostingEnvironment;
}
[HttpGet("")]
public IActionResult Get()
{
return new MultipartResult()
{
new MultipartContent()
{
ContentType = "text/plain",
FileName = "File.txt",
Stream = this.OpenFile("File.txt")
},
new MultipartContent()
{
ContentType = "application/json",
FileName = "File.json",
Stream = this.OpenFile("File.json")
}
};
}
private Stream OpenFile(string relativePath)
{
return System.IO.File.Open(
Path.Combine(this.hostingEnvironment.WebRootPath, relativePath),
FileMode.Open,
FileAccess.Read);
}
}
Implementation
public class MultipartContent
{
public string ContentType { get; set; }
public string FileName { get; set; }
public Stream Stream { get; set; }
}
public class MultipartResult : Collection<MultipartContent>, IActionResult
{
private readonly System.Net.Http.MultipartContent content;
public MultipartResult(string subtype = "byteranges", string boundary = null)
{
if (boundary == null)
{
this.content = new System.Net.Http.MultipartContent(subtype);
}
else
{
this.content = new System.Net.Http.MultipartContent(subtype, boundary);
}
}
public async Task ExecuteResultAsync(ActionContext context)
{
foreach (var item in this)
{
if (item.Stream != null)
{
var content = new StreamContent(item.Stream);
if (item.ContentType != null)
{
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(item.ContentType);
}
if (item.FileName != null)
{
var contentDisposition = new ContentDispositionHeaderValue("attachment");
contentDisposition.SetHttpFileName(item.FileName);
content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
content.Headers.ContentDisposition.FileName = contentDisposition.FileName;
content.Headers.ContentDisposition.FileNameStar = contentDisposition.FileNameStar;
}
this.content.Add(content);
}
}
context.HttpContext.Response.ContentLength = content.Headers.ContentLength;
context.HttpContext.Response.ContentType = content.Headers.ContentType.ToString();
await content.CopyToAsync(context.HttpContext.Response.Body);
}
}
From MSDN
MSDN has a document that lists a lot of the multipart subtypes. The multipart/byteranges seems most appropriate for sending multiple files in an HTTP Response for download by the client application. The bold part is particularly relevant.
The multipart/byteranges content type is defined as a part of the HTTP message protocol. It includes two or more parts, each with its own Content-Type and Content-Range fields. The parts are separated using a MIME boundary parameter. It allows for binary as well as 7-bit and 8-bit files to be sent as multiple parts with the lengths of the parts being specified in the header of each part. Note that while HTTP makes provisions for using MIME for HTTP documents, HTTP is not strictly MIME-compliant. (Emphasis added.)
From RFC2068
RFC2068, section 19.2 provides a description of multipart/byteranges. Again, the bold part is relevant. Each byterange can have its own Content-type and it turns out can also have its own Content-disposition.
The multipart/byteranges media type includes two or more parts, each with its own Content-Type and Content-Range fields. The parts are separated using a MIME boundary parameter. (Emphasis added.)
The RFC also provides this technical definition:
Media Type name: multipart
Media subtype name: byteranges
Required parameters: boundary
Optional parameters: none
Encoding considerations: only "7bit", "8bit", or "binary" are permitted
Security considerations: none
The best part of the RFC is its example, which the ASP.NET Core sample below illustrates.
HTTP/1.1 206 Partial content
Date: Wed, 15 Nov 1995 06:25:24 GMT
Last-modified: Wed, 15 Nov 1995 04:58:08 GMT
Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
--THIS_STRING_SEPARATES
Content-type: application/pdf
Content-range: bytes 500-999/8000
...the first range...
--THIS_STRING_SEPARATES
Content-type: application/pdf
Content-range: bytes 7000-7999/8000
...the second range
--THIS_STRING_SEPARATES--
Note that they are sending two PDFs! That is just what you're needing.
One ASP.NET Core Approach
Here is a code sample that works on Firefox. That is, Firefox downloads three image files, which we can open with Paint. The source is on GitHub.
The sample uses app.Run(). To adapt the sample to a controller action, inject IHttpContextAccessor into your controller and write to _httpContextAccessor.HttpContext.Response in your action method.
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
private const string CrLf = "\r\n";
private const string Boundary = "--THIS_STRING_SEPARATES";
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
var response = context.Response;
response.ContentType = $"multipart/byteranges; boundary={Boundary}";
// TODO Softcode the 'Content-length' header.
response.ContentLength = 13646;
var contentLength = response.ContentLength.Value;
await response.WriteAsync(Boundary + CrLf);
var blue = new FileInfo("./blue.jpg");
var red = new FileInfo("./red.jpg");
var green = new FileInfo("./green.jpg");
long start = 0;
long end = blue.Length;
await AddImage(response, blue, start, end, contentLength);
start = end + 1;
end = start + red.Length;
await AddImage(response, red, start, end, contentLength);
start = end + 1;
end = start + green.Length;
await AddImage(response, green, start, end, contentLength);
response.Body.Flush();
});
}
private async Task AddImage(HttpResponse response, FileInfo fileInfo,
long start, long end, long total)
{
var bytes = File.ReadAllBytes(fileInfo.FullName);
var file = new FileContentResult(bytes, "image/jpg");
await response
.WriteAsync($"Content-type: {file.ContentType.ToString()}" + CrLf);
await response
.WriteAsync($"Content-disposition: attachment; filename={fileInfo.Name}" + CrLf);
await response
.WriteAsync($"Content-range: bytes {start}-{end}/{total}" + CrLf);
await response.WriteAsync(CrLf);
await response.Body.WriteAsync(
file.FileContents,
offset: 0,
count: file.FileContents.Length);
await response.WriteAsync(CrLf);
await response.WriteAsync(Boundary + CrLf);
}
}
Note: this sample code requires refactoring before reaching production.

500 Internal Server Error ajax post json

I built a website using ASP.NET MVC and Knockoutjs. This is hosted on IIS on Windows Sever 2012. There is another web application where I use ajax to POST and that application does not give any errors. The Submit button on the website is binded using the click bind to this function. This works when I run it in Debug mode on the localhost.
self.SubmitEvaluation = function () {
reqUrl = "/Home/SubmitEvaluation";
$.ajax({
type: "POST",
url: reqUrl,
data: JSON.stringify({ evaluation: ko.toJSON(self) }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
if (response == 1) {
self.EvalComplete(true);
} else {
self.EvalComplete(false);
alert("Submission Failed. Please resubmit!!!")
}
},
error: function (jqXHR, exception) {
if (jqXHR.status === 0) {
alert('Not connect.\n Verify Network.');
} else if (jqXHR.status == 404) {
alert('Requested page not found. [404]');
} else if (jqXHR.status == 500) {
alert('Internal Server Error [500].'+exception.toString());
} else if (exception === 'parsererror') {
alert('Requested JSON parse failed.');
} else if (exception === 'timeout') {
alert('Time out error.');
} else if (exception === 'abort') {
alert('Ajax request aborted.');
} else {
alert('Uncaught Error.\n' + jqXHR.responseText);
}
}
});
In the home controller I have these two web methods.
[HttpGet]
public string Test()
{
Logger.Logger.WriteLog("Test", "Inside Test");
TestModel product = new TestModel();
product.Name = "Apple";
product.Price = "3.99M";
return JsonConvert.SerializeObject(product);
}
[HttpPost]
public int SubmitEvaluation(string evaluation)
{
Logger.Logger.WriteLog("Submitevaluation", "Inside SubmitEvaluation");
int result = -1;
try
{
EvaluationModel eval = JsonConvert.DeserializeObject<EvaluationModel>(evaluation);
MySqlConnection conn = new MySqlConnection(connStr);
conn.Open();
string sql = "INSERT INTO xyz table blah blah blah";
MySqlCommand cmd = new MySqlCommand(sql, conn);
result = cmd.ExecuteNonQuery();
}
catch(Exception ex)
{
Logger.WriteLog("Submitevaluation", ex.ToString());
}
return result;
}
I receive Internal Sever Error 500 from the Ajax request when I click on the Submit button.
But if I do this http://xxx.xxx.xxx.xxx/Home/Test I get the json result back {"Name":"Apple","Price":"3.99M"}.
Response header from Fiddler
HTTP/1.1 500 Internal Server Error
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 4.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Jan 2014 16:22:16 GMT
Content-Length: 276
After turning on customer errors and detailed error message I am receiving this message.
Could not load file or assembly 'MySql.Data, Version=6.8.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d' or one of its dependencies. The system cannot find the file specified
I downloaded the Mysql connector from http://dev.mysql.com/downloads/connector/net/ and I added the assembly by right clicking on References > Extensions and selecting the 4.0 version. I also tried the 4.5.
Uninstalled 6.8 and downloaded 6.7. Works now.

Resources