Calling an API on Xamarin getting Bad Request - asp.net

So, I'm new to Xamarin and I'm trying to call API. I didn't have any trouble when I want to get data from a wheather api. But when I try to call my own API which is created with ASP.NET RESTFull and help of internet.
So this is my code. I can get what I need when I use ;
http://localhost:1658/api/person
on my browser, it works perfectly. But when I use;
string querystring = "http://10.0.2.2:1658/api/person";
JContainer results = await GetDataFromService(querystring);
}
public static async Task<JContainer> GetDataFromService(string queryString)
{
HttpClient client = new HttpClient();
var response = await client.GetAsync(queryString);
JContainer data = null;
if (response.IsSuccessStatusCode)
{
string json = response.Content.ReadAsStringAsync().Result;
data = (JContainer)JsonConvert.DeserializeObject(json);
}
return data;
}
it didn't work.
This is my API codes:
// This code piece in PersonController.cs
// GET: api/Person
public ArrayList Get()
{
PersonPersistance pp = new PersonPersistance();
return pp.getPersons();
}
// This piece of code in PersonPersistance.cs
public Person getPerson(long ID)
{
Person p = new Person();
//MySql.Data.MySqlClient.MySqlDataReader MSR = null;
SqlDataReader MSR = null;
string selectquery = "select * from person where Id="+ID.ToString();
//MySql.Data.MySqlClient.MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand(selectquery,conn);
SqlCommand cmd = new SqlCommand(selectquery, conn);
//MSR = cmd.ExecuteReader();
MSR = cmd.ExecuteReader();
if(MSR.Read())
{
p.Id = MSR.GetInt32(0);
p.FirstName = MSR.GetString(1);
p.LastName = MSR.GetString(2);
p.Pay = MSR.GetInt32(3);
p.BeginDay = MSR.GetDateTime(4);
p.EndDate = MSR.GetDateTime(5);
return p;
}
else
{
return null;
}
}

Try adding await to your ReadAsStringAsync():
public static async Task<JContainer> GetDataFromService(string queryString)
{
HttpClient client = new HttpClient();
var response = await client.GetAsync(queryString);
JContainer data = null;
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
data = JsonConvert.DeserializeObject<JContainer>(json);
}
return data;
}

Related

ASP.NET WEB API cant upload multipart/form-data (image) to Web server

After uploading image through ASP.NET WEB API successfuly through localhost . I uploaded my project to the hosting server but this time i got the error as
an error has occured
This is my controller
tutorEntities entities = new tutorEntities();
[HttpPost]
public HttpResponseMessage ImageUp()
{
var httpContext = (HttpContextWrapper)Request.Properties["MS_HttpContext"];
img std = new img();
// std.Title = httpContext.Request.Form["Title"];
// std.RollNo = httpContext.Request.Form["RollNo"];
// std.Semester = httpContext.Request.Form["Semester"];
HttpResponseMessage response = new HttpResponseMessage();
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
string random = Guid.NewGuid().ToString();
string url = "/UserImage/" + random + httpRequest.Files[0].FileName.Substring(httpRequest.Files[0].FileName.LastIndexOf('.'));
Console.WriteLine(url);
string path = System.Web.Hosting.HostingEnvironment.MapPath(url);
httpRequest.Files[0].SaveAs(path);
std.Path = "http://localhost:2541/" + url;
}
entities.imgs.Add(std);
entities.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK);
}
Ensure that AppPoolIdentity user has write permissions on the UserImage folder. Also, catch the exception in code for debugging:
try {
var httpContext = (HttpContextWrapper)Request.Properties["MS_HttpContext"];
img std = new img();
// std.Title = httpContext.Request.Form["Title"];
// std.RollNo = httpContext.Request.Form["RollNo"];
// std.Semester = httpContext.Request.Form["Semester"];
HttpResponseMessage response = new HttpResponseMessage();
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
string random = Guid.NewGuid().ToString();
string url = "/UserImage/" + random + httpRequest.Files[0].FileName.Substring(httpRequest.Files[0].FileName.LastIndexOf('.'));
Console.WriteLine(url);
string path = System.Web.Hosting.HostingEnvironment.MapPath(url);
httpRequest.Files[0].SaveAs(path);
std.Path = "http://localhost:2541/" + url;
}
entities.imgs.Add(std);
entities.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK);
}
catch(Exception ex) {
var response = new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(ex.ToString()),
ReasonPhrase = "Error"
}
throw new HttpResponseException(response);
}

Odata naming file return error message of the

I have this custom Odata function to download pdf from download pdf database. I have some issues
1.with Pdf name does not name "reportname.pdf" it is named response.pdf as
2.return error message of reportBinary is null
[HttpGet]
[ODataRoute("GetDownloadReport(downloadId={downloadId})")]
public HttpResponseMessage GetDownloadReport(Guid downloadId)
var received = DateTime.UtcNow;
byte[] reportBinary = null;
string queryString = "SELECT report FROM downloads WHERE id = #downloadId ";
bool success = false;
using (SqlConnection conn = new SqlConnection(connectionString))
{
//get the binary from database
}
HttpResponseMessage response = null;
try
{
if (reportBinary == null)
return Request.CreateResponse(HttpStatusCode.Gone);
response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new ByteArrayContent(reportBinary);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
FileName = "PORTName.pdf"
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return response;
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.Gone);
}
}
try to set filename manually:
String headerInfo = "attachment; filename=" + System.Web.HttpUtility.UrlPathEncode("PORTName.pdf");
response.Content.Headers.Add("Content-Disposition", headerInfo);
I'm not sure what do you want to do about error message, but if you mean setting string content, just set it ;)
response = Request.CreateResponse(HttpStatusCode.Gone);
response.Content = new StringContent(...);
return response;
Consider using NotFound instead of Gone status code (Gone has very specific meaning).

Internal Server Error 500 on async upload asp mvc 5

Just started using ASP.Net 4.5 and my API always returns Internal Server Error.
Upload API
public class UploadController : ApiController
{
public async Task<HttpResponseMessage> PostFile()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data/uploads/");
var provider = new CustomMultipartFormDataStreamProvider(root);
try
{
await Request.Content.ReadAsMultipartAsync(provider);
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
}
My Controller
var message = new HttpRequestMessage();
var content = new MultipartFormDataContent();
message.Method = HttpMethod.Post;
message.Content = content;
message.RequestUri = new Uri("http://localhost:12345/api/upload/");
var client = new HttpClient();
client.SendAsync(message).ContinueWith(task =>
{
var result = task.Result.ReasonPhrase;
if (task.Result.IsSuccessStatusCode)
{
//do something
}
});
The files are saved in the location (/App_Data/uploads/) but why is the status code always 500?
Please enlighten me. Thanks
Here is part of working controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(Product product, HttpPostedFileBase file)
{
if (!ModelState.IsValid)
return PartialView("Create", product);
if (file != null)
{
var fileName = Path.GetFileName(file.FileName);
var guid = Guid.NewGuid().ToString();
var path = Path.Combine(Server.MapPath("~/Content/Uploads/ProductImages"), guid + fileName);
file.SaveAs(path);
string fl = path.Substring(path.LastIndexOf("\\"));
string[] split = fl.Split('\\');
string newpath = split[1];
string imagepath = "Content/Uploads/ProductImages/" + newpath;
using (MemoryStream ms = new MemoryStream())
{
file.InputStream.CopyTo(ms);
byte[] array = ms.GetBuffer();
}
var nId = Guid.NewGuid().ToString();
// Save record to database
product.Id = nId;
product.State = 1;
product.ImagePath = imagepath;
product.CreatedAt = DateTime.Now;
db.Products.Add(product);
await db.SaveChangesAsync();
TempData["message"] = "ProductCreated";
//return RedirectToAction("Index", product);
}
// after successfully uploading redirect the user
return Json(new { success = true });
}

Parameter has all propertys after webrequest

I have a really simple ASP.NET Api Controller with one method.
public HttpResponseMessage<User> Post(User user)
{
return new HttpResponseMessage<User>(new User() { Name = "New User at Server" });
}
My debugger says that the method is called but the problem is that the parameter "user" has all its content set to null; I am using Fiddler to look at request and response.. and all looks good.
This is my service code in the client.
public void AddUser(Models.User user, Action<Models.User> ShowResult)
{
var uiThreadScheduler = TaskScheduler.FromCurrentSynchronizationContext();
string url = "http://localhost:4921/User";
Uri uri = new Uri(url, UriKind.Absolute);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var sendWebPost = Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null)
.ContinueWith(task =>
{
Tuple<string, string>[] stringToSend = { Tuple.Create<string, string>("user", ObjectToJson<Models.User>(user)) };
var bytesToSend = GetRequestBytes(stringToSend);
using (var stream = task.Result)
stream.Write(bytesToSend, 0, bytesToSend.Length);
}
).ContinueWith(task =>
{
Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null)
.ContinueWith<WebResponse>(task2 => { ValidateResponse(task2); return task2.Result; })
.ContinueWith<Models.User>(task3 => {return JsonToObject<Models.User>(task3);})
.ContinueWith(task4 => { TryClearWorking(); ShowResult(task4.Result); }, uiThreadScheduler);
});;
}
public static string ObjectToJson<T>(T obj) where T : class
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
MemoryStream stream = new MemoryStream();
StreamReader sr = new StreamReader(stream);
serializer.WriteObject(stream, obj);
sr.BaseStream.Position = 0;
string jsonString = sr.ReadToEnd();
return jsonString;
}
protected static byte[] GetRequestBytes(Tuple<string, string>[] postParameters)
{
if (postParameters == null || postParameters.Length == 0)
return new byte[0];
var sb = new StringBuilder();
foreach (var key in postParameters)
sb.Append(key.Item1 + "=" + key.Item2 + "&");
sb.Length = sb.Length - 1;
return Encoding.UTF8.GetBytes(sb.ToString());
}
Anyone who can give me some ideas where to start to look for errors.....
You need to set the Content-Length header.

how to parse xml string from Post method response?

I have a xml string that return from Post method:
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
HttpStatusCode rcode = response.StatusCode;
var stream = new GZipInputStream(response.GetResponseStream());
using (StreamReader reader = new StreamReader(stream))
{
responseString = reader.ReadToEnd();
}
response.Close();
}
The responseString is the string I want to parse, using parseXmlString class below. However I can't call the method parseXmlString directly because of the static. How can I pass the responseString to the parseXmlString method to have them parse out and bind to the listBox. Or anyway to have the same result would be great.
void parseXmlString()
{
byte[] byteArray = Encoding.UTF8.GetBytes(responseString);
MemoryStream str = new MemoryStream(byteArray);
str.Position = 0;
XDocument xdoc = XDocument.Load(str);
var data = from query in xdoc.Descendants("tracks").Elements("item")
select new searchResult
{
artist = (string)query.Element("artist"),
album = (string)query.Element("album"),
track = (string)query.Element("track"),
// artistA = (string)query.Element("artists").Element("artist"),
};
// ListBox lb = new ListBox();
listBox1.ItemsSource = data;
var data1 = from query in xdoc.Descendants("artists").Elements("item")
select new searchResult
{
artistA = (string)query.Element("artist"),
};
listBox2.ItemsSource = data1;
}
Your approach is inversed logic. You know that you can have return values on methods, right?-)
What you need to do is let your ParseXmlString method take the responseString as a parameter, and let it return the created IEnumerable, like this:
private IEnumerable<SearchResult> ParseXmlString(responseString)
{
XDocument xdoc = XDocument.Load(responseString);
var data =
from query in xdoc.Descendants("tracks").Elements("item")
select new SearchResult
{
Artist = (string)query.Element("artist"),
Album = (string)query.Element("album"),
Track = (string)query.Element("track"),
};
return
from query in xdoc.Descendants("artists").Elements("item")
select new SearchResult
{
ArtistA = (string)query.Element("artist"),
};
}
And change your async code handling, to perform a callback to your UI thread, when it's done reading out the responseString.
Then, on your UI thread, you would do:
// This being your method to get the async response
GetResponseAsync(..., responseString =>
{
var searchResults = ParseXmlString(responseString);
listBox2.ItemsSource = searchResults;
})
You can see this answer, if you need some basic understanding of callbacks: Callbacks in C#

Resources