I have a problem when I am trying to access my ASP.NET Web Api 2 application running on the localhost from windows phone 8 application. I have tried and looked for a lot examples how to do it but with no result. I tested my api using Fiddler and it works. I tested to access it from web application and it works but when I tried to access it from windows phone 8 app it doesn't. Can you tell me how to configure my windows phone 8 emulator to access it? Thank you in advance.
The emulator is a virtual machine so "localhost" inside your phone app means the emulator itself, not your host machine where you're running your web service. To access it, you have to provide the actual IP address of your host computer in the local network instead of "localhost". You can see what your IP is by running ipconfig in the cmd console.
here is a detail artical on accessing web api methods in Windows Phone 8
Calling Web API from a Windows Phone 8
to be specific here is how you get data from web API
string apiUrl = #"http://www.contoso.com/api/Books";
WebClient webClient = new WebClient();
webClient.Headers["Accept"] = "application/json";
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadCatalogCompleted);
webClient.DownloadStringAsync(new Uri(apiUrl));
private void webClient_DownloadCatalogCompleted(object sender, DownloadStringCompletedEventArgs e)
{
try
{
this.Items.Clear();
if (e.Result != null)
{
var books = JsonConvert.DeserializeObject<BookDetails[]>(e.Result);
int id = 0;
foreach (BookDetails book in books)
{
this.Items.Add(new ItemViewModel()
{
ID = (id++).ToString(),
LineOne = book.Title,
LineTwo = book.Author,
LineThree = book.Description.Replace("\n", " ")
});
}
this.IsDataLoaded = true;
}
}
catch (Exception ex)
{
this.Items.Add(new ItemViewModel()
{
ID = "0",
LineOne = "An Error Occurred",
LineTwo = String.Format("The following exception occured: {0}", ex.Message),
LineThree = String.Format("Additional inner exception information: {0}", ex.InnerException.Message)
});
}
}
Hope this helps
Related
I have an app running on Windows Phone 8.1 which calls a URL via InAppBrowser plugin. This URL is supposed to ask for the user certificate stored on a virtual smartcard on the phone.
When I call the URL via Internet Explorer, I am asked for my PIN to unlock the virtual smartcard but in the InAppBrowser, this doesn't work. No PIN prompt, nothing.
Iterating through the Certificates yielded from
IReadOnlyList<Certificate> certStores = await CertificateStores.FindAllAsync();
I can see the certificate at app runtime but InAppBrowser doesn't seem to query for them. Do I have to copy its reference to another certificate store or is InAppBrowser not capable of establishing SSL with user certificates ?
The issue is with the webview component, x-ms-webview to be more precisely. InAppBrowser plugin uses this component internally.
Found a workaround mentioned here, it kinda sounds like a security issue tbh so this could get fixed in the future but here are more details on said workaround:
Make a request to the URL which is supposed to trigger virtual smartcard unlock to access the user certificate, but with the HttpClient at native level (C#)
I've created another Windows Runtime Component in my solution which does a simple POST to the url I want to access from InAppBrowser later on.
While setting up the Windows.Web.Http.HttpClient, I fetch the user certificate from the smartcard and set it as HttpBaseProtocolFilter.ClientCertificate.
public sealed class SSLHelper
{
private static String errorMessage = "";
private static String statusMessage = "";
public static IAsyncOperation<Boolean> establishSSLConnection(String url)
{
return connect(url).AsAsyncOperation<Boolean>();
}
public static String getErrorMessage()
{
return SSLHelper.errorMessage;
}
public static String getStatusMessage()
{
return SSLHelper.statusMessage;
}
private static async Task<Boolean> connect(String urlString)
{
Certificate clientCert = await getCertificateAsync();
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
filter.ClientCertificate = clientCert;
HttpClient client = new HttpClient(filter);
try
{
System.Uri url = new System.Uri(urlString);
HttpResponseMessage response = await client.PostAsync(url, new HttpStringContent(""));
response.EnsureSuccessStatusCode();
SSLHelper.statusMessage = response.StatusCode.ToString();
return true;
}
catch (Exception e)
{
SSLHelper.errorMessage = e.ToString();
return false;
}
}
private static async Task<Certificate> getCertificateAsync()
{
CertificateQuery query = new CertificateQuery();
query.IssuerName = "Sample Issuer";
IReadOnlyList<Certificate> certStores = await CertificateStores.FindAllAsync(query);
return certStores.FirstOrDefault<Certificate>();
}
}
Make that code return as a promise on Javascript level and once it resolves, start the code which uses InAppBrowser to access the secure URL again. The native request causes the PIN prompt for virtual smartcard access, once you have entered the correct PIN, InAppBrowser / WebView can magically establish the connection.
I have a simple test Web API that is up and working. When I run it and enter http://localhost:xxxxx/api/user in the browser it returns a JSON empty array and it has full functionality when I test it with Fiddler. But when I try and test it with the Chrome REST Console (with a GET Request to http://localhost:xxxxx/api/user) I get a "Connection Failed! Check your connectivity and try again" error.
Api Controller:
public class UserController : ApiController
{
private UserRepository repository = new UserRepository();
public int Put(int id, [FromBody]int amount)
{
var user = repository.GetByID(id);
if (user == null) return -1;
user.Total += amount;
repository.Save(user);
return user.Total;
}
public int Post([FromBody]CreateUserRequest request)
{
var user = new User { Goal = request.Goal, Name = request.Name, Total = 0 };
repository.Add(user);
return user.UserId;
}
public IEnumerable<User> Get() { return new List<User>(repository.GetAll()); }
public User Get(int id) { var user = repository.GetByID(id); return user; }
public class CreateUserRequest
{
public string Name { get; set; }
public int Goal { get; set; }
}
The REST Console had formerly worked with this test Web API. The only reference I could find on the web referenced un-signed certificates. I had created a signed certificate for localhost in IIS but I removed it, restarted the computer and the REST Console still returns the same error. Not that that should matter since the Web API is running in IIS Express. I have also tried it with other Web API's on my local machine and get the same error.
Does anyone have any idea as to the possible source of the problem or how I might troubleshoot it? As I said the Web API's are fully function when tested with Fiddler. The Web API was created with and is being ran from VS 2012 on a Windows 7 Ultimate workstation.
I subsequently noticed that when ever I ran an app from Visual Studio in Chrome that it would redirect to https (even for apps that were not using SSL) and generate an SSL error.
I cleared all browsing data in Chrome and both the Chrome and the REST Console problems cleared.
I'm a little bit new to all of these technologies so I'll try to be as clear as I can.
I'm writing a windows phone app that sends data in string format to a server:
public class sendDataControl
{
private string response = "";
public void sendToServer(string FullSTR)
{
try
{
WebClient webClient = new WebClient();
Uri uri = new Uri("http://pricequeryserver.azurewebsites.net/api/ReceiptDataService/?incomingdata=");
webClient.UploadStringAsync(uri,FullSTR);
webClient.UploadStringCompleted += new UploadStringCompletedEventHandler(webClient_UploadStringCompleted);
}
catch (Exception ex)
...
...
}
}
void webClient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
if (e.Error != null)
{
responseXml=e.Error.Message;
MessageBox.Show(responseXml);
return;
}
else
{
responseXml = e.Result;
}
}
}
The server is an MVC4, basic, with api controller I added, that needs to get the data sent from the mobile.
As a test I'm just getting back a string that I send:
public class ReceiptDataServiceController : ApiController
{
private ReceiptContext db = new ReceiptContext();
...
...
public string GetDataFromMobile(string IncomingData)
{
return IncomingData;
}
}
While running the application I get an error via responseXml:
"The remote server returned an error: NotFound".
The server returns the right answer from all kinds of browsers, while on IIS and on the azure but not from the mobile emulator.
Any suggestions?
If you take a look at the documentation for UploadStringAsync overload you are using, you will notice that it sends data using POST method. While in your controller you have only implemented GET. And for your
You have to use other overload of UploadStringAsync, which lets you specify the HTTP VERB to use. And you must specify GET. Your client code should be converted to:
webClient.UploadStringAsync(uri,"GET", FullSTR);
And the best solution for simple GET operations like your is to actually use DownloadStringAsync:
var fullUri = new Uri("http://pricequeryserver.azurewebsites.net/api/ReceiptDataService/?incomingdata=" + FullStr);
webClient.DownloadStringAsync(fullUri);
Anyway, your question has nothing to do with Windows Azure, thus the removed tag.
I'm new to the world of programming, and am trying to develop an app that uses OCR.
I want the app to convert a singular receipt into text (nothing too complex).
However my problem is that i'm finding a lack of information for OCR on WP8, and how to implement it.
I would have though that it's a built in function of WP and that information would be easily accessible as to how to implement it.
Anyone know where I could look, or a simple example snippet of code I could use?
Not wanting a subscription based service.
Microsoft recently released the OCR Library for Windows Runtime. Jerry Nixon has posted a video guiding you though it, and there is also an msdn article.
Jerry Nixon's Blog
MSDN
You can try using the same OCR service that the Bing Lens uses. If you haven't tried it: open camera, change lens to bing lens and try it out
The service endpoint is http://ocrrest.bingvision.net/V1. It also gives you information about the location of the detected text with their bounding boxes
Probably some fiddler analysis will help you to send your image in a similar fashion.
I have a little snippet below which expects the image as byte array
public static readonly string ocrServiceUrl = "http://ocrrest.bingvision.net/V1"; // was: "platform.bing.com/ocr/V1";
public static readonly string ocrLanguage = "en";
public static async Task<JsonObject> MakeOcrJSON(byte[] image)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format("{0}/Recognize/{1}", ocrServiceUrl, ocrLanguage));
request.Method = "POST";
using (Stream requestStream = await request.GetRequestStreamAsync())
{
requestStream.Write(image, 0, image.Length);
}
try
{
using (HttpWebResponse response = (HttpWebResponse) (await request.GetResponseAsync()))
{
using (var responseStream = new StreamReader(response.GetResponseStream()))
{
var json = JsonObject.Parse(responseStream.ReadToEnd());
return json;
}
}
}
catch (WebException we)
{
using (Stream responseStream = we.Response.GetResponseStream())
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(OcrResponse));
OcrResponse ocrResponse = (OcrResponse)serializer.ReadObject(responseStream);
string ErrorMessage = "Unknown Error";
if (ocrResponse.OcrFault.HasValue)
{
ErrorMessage = string.Format(
"HTTP status code: {0} Message: {1}",
ocrResponse.OcrFault.Value.HttpStatusCode,
ocrResponse.OcrFault.Value.Message);
}
throw new Exception(ErrorMessage);
}
}
}
I'm trying to parse Twitter timeline, but I have an error: The remote server returned an error: NotFound.
Here is code:
private void GetUserTimeLine(string userName)
{
WebClient wcTwitterTimeline = new WebClient();
wcTwitterTimeline.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wcTwitterTimeline_DownloadStringCompleted);
wcTwitterTimeline.DownloadStringAsync(new System.Uri("http://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=" + userName));
}
void wcTwitterTimeline_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
List<RootObject> tweets = JsonConvert.DeserializeObject<List<RootObject>>(e.Result);
this.listboxMyTimeline.ItemsSource = tweets;
Dispatcher.BeginInvoke(() =>
{
listboxMyTimeline.Visibility = Visibility.Visible;
txtBoxNewTweet.Visibility = Visibility.Visible;
btnPostTweet.Visibility = Visibility.Visible;
});
}
Error begins here:
List<RootObject> tweets = JsonConvert.DeserializeObject<List<RootObject>>(e.Result);
The 404 Not Found might be because you're URL scheme is http and should be https. After you resolve this, your next error might be 401 Unauthorized because Twitter API v1.1 requires OAuth authentication. You might want to check out the Twitter API FAQ and referenced docs for more details.