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
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);
}
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).
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 });
}
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.
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#