SOAP Parsing in windows phone 7 - windows

I will searching since 10 days but i have not succeed in soap parsing in wp7.
My code is below. I get the The remote server returned an error: NotFound. and System.Net.WebException.
code is below :
private const string AuthServiceUri = "http://manarws.org/WS/manarService.asmx";
private const string AuthEnvelope =
#"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<fnGetNewsResponse xmlns=""http://tempuri.org/"">
<fnGetNewsResult></fnGetNewsResult>
</fnGetNewsResponse>
</soap:Body>
</soap:Envelope>";
public void Authenticate()
{
HttpWebRequest spAuthReq = HttpWebRequest.Create(AuthServiceUri) as HttpWebRequest;
spAuthReq.Headers["SOAPAction"] = "http://tempuri.org/fnGetNews";
spAuthReq.ContentType = "text/xml; charset=utf-8";
spAuthReq.Method = "POST";
spAuthReq.BeginGetRequestStream(new AsyncCallback(spAuthReqCallBack), spAuthReq);
}
private void spAuthReqCallBack(IAsyncResult asyncResult)
{
UTF8Encoding encoding = new UTF8Encoding();
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
System.Diagnostics.Debug.WriteLine("REquest is :" + request.Headers);
Stream _body = request.EndGetRequestStream(asyncResult);
string envelope = string.Format(AuthEnvelope,"","");
System.Diagnostics.Debug.WriteLine("Envelope is :" + envelope);
byte[] formBytes = encoding.GetBytes(envelope);
_body.Write(formBytes, 0, formBytes.Length);
_body.Close();
request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);
}
private void ResponseCallback(IAsyncResult asyncResult)
{
System.Diagnostics.Debug.WriteLine("Async Result is :" + asyncResult);
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);
System.Diagnostics.Debug.WriteLine("Response is :::::::::::::::::::----" + request.EndGetResponse(asyncResult));
if (request != null && response != null)
{
if (response.StatusCode == HttpStatusCode.OK)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
string responseString = reader.ReadToEnd();
}
}
}
I get the error in HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult); line...
So, Please help me.
Thanks.

Maybe I am missing something but why not just adding a service reference ?
The service located at 'http://manarws.org/WS/manarService.asmx' is a classic web service and you can browse wsdl. You can add a reference in Visual Studio. It will generate a proxy class to call this webservice. Manual soap parsing is quite painful.
EDIT :
1) Right clic on service reference in your project.
2) Enter your service url. Then click Go.
3) You will have new classes in your project.
Just use them as you want. Exemple :
public void GetBranches()
{
ManarServiceReference.manarServiceSoapClient client = new ManarServiceReference.manarServiceSoapClient();
client.fnGetBranchesCompleted += new EventHandler<ManarServiceReference.fnGetBranchesCompletedEventArgs>(client_fnGetBranchesCompleted);
client.fnGetBranchesAsync();
}
void client_fnGetBranchesCompleted(object sender, ManarServiceReference.fnGetBranchesCompletedEventArgs e)
{
//TODO
}

Follow these steps to know how to use a SOAP service
-- Create a new project.
-- Right-click on the Project name and click on "Add Service Reference"...
Then provide address as "http://manarws.org/WS/manarService.asmx?wsdl" and click Go.
-- Once service information is downloaded, provide Namespace something like
"MyMemberService" at the bottom and click Ok.
Now that your proxy classes should be ready.
Go to your Mainpage.xaml.cs and type 'client' there..you should probably get a class with the name "ManarServiceClient".
If you get that, then try to call the suitable methods of that class.
For an example,
ManarServiceClient client = new ManarServiceClient();
client.fnGetNewsResponseCompleted += new EventHandler<fnGetNewsResponseCompletedEventArgs>(client_fnGetNewsResponseCompleted);
client.fnGetNewsResponseAsync();
Note: I am not with my working system, so cannot give you exact code. All the above is a guessed code and shall point you in the right direction. Will test my code and update soon.

If you create of an asmx web service. The first call is incredibly slow.

Related

Client-Side error when uploading image on server ASP.NET Core

I am struggling with uploading an image from thew client-side to a folder on the server-side in .Net Core.I used Postman to check if the method on the server-side is working and it does without any problem,but when I try to upload an image from the client-side,I get an error on the server-side of type NullReferenceException:Object reference not set to an instance of an object.This is the Post method on the server-side:
[HttpPost]
public async Task Post(IFormFile file)
{
if (string.IsNullOrWhiteSpace(_environment.WebRootPath))
{
_environment.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
}
var uploads = Path.Combine(_environment.WebRootPath, "uploads");
//var fileName = file.FileName.Split('\\').LastOrDefault().Split('/').LastOrDefault();
if (!Directory.Exists(uploads)) Directory.CreateDirectory(uploads);
if (file.Length > 0)
{
using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
}
}
Apparently the method is thrown where I check if the length of the file is bigger than 0.On the client-side I get error "500 internal server error" and I tried to check using the debugger where exactly the error is thrown but i can't find anything that could resemble an error of some sort.This is the API method for the client-side:
public async Task UploadPictureAsync(MediaFile image)
{
User user = new User();
string pictureUrl = "http://10.0.2.2:5000/api/UploadPicture";
HttpContent fileStreamContent = new StreamContent(image.GetStream());
// user.Picture=GetImageStreamAsBytes(image.GetStream());
fileStreamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") {FileName=Guid.NewGuid() + ".Png",Name="image"};
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
using (var client = new HttpClient(clientHandler))
{
using (var formData = new MultipartFormDataContent())
{
formData.Add(fileStreamContent);
var response = await client.PostAsync(pictureUrl, formData);
if(response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
}
}
}
}
The image is declared in the Model as byte array:
public byte[] Picture { get; set; }
Does someone understand why my POST method has this behavior since the server-side works perfectly but fails when I try to upload an image from the client-side?What I find weird though is that when i read the error and I look at the Content-Type it is "text/plain" instead of "form-data" and I have tried to set it at the MutipartFormDataContent like this:
formData.Headers.ContentType.MediaType = "multipart/form-data";
I also tried to set the MediaTypeHeaderValue on the client like this:
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
I still get the wrong content type.
I have also tried a different approach with Stream instead of MediaFile but without any luck as it did not even hit the break point in debugger mode for the response.Any help would be appreciated! :)
I have managed to find the answer finalllyyyyy!!!The problem was on the client-side as I suspected and guess what,it was all about the correct name.It turns out that since on the server side I have IFormFile file I had to change the client side to take the parameter name "file" instead of image as well so that it could work.Thank you #Jason for the suggestions as I didn't understand the error from the first place and did some debugging on the server-side to help me figure it out.

WebRequest returns 404 when switching to SSL

Having built an app using PCL method in Xamarin and have had it working 100% using standard HTTP I now changed the remote test server to use SSL with self signed certs.
The app contacts a custom API for logging onto a server and querying for specific data.
I've changed the app to look at SSL now and initially got an error regarding Authentication not working or something but turned off SSL related errors for testing using:
ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true;
in my AppDelegate files FinishedLaunching method which got over that error.
I'm now getting a 404 / protocol error when trying to do my Login POST to the given URL.
I am using HttpWebRequest for my RESTful calls and this works fine if I change back to plain http.
Not sure why but some articles suggested using ModernHttpClient, which I did. I imported the component (also added the package using NuGet) to no avail.
Am I missing something else that I should be configuring in my code related to httpwebresponse when contacting the SSL server or is this component simply incapable of speaking to an SSL server?
My login function is as follows (Unrelated code removed/obfuscated):
public JsonUser postLogin(string csrfToken, string partnerId, string username, string password){
string userEndPoint = SingletonAppSettngs.Instance ().apiEndPoint;
userEndPoint = userEndPoint.Replace ("druid/", "");
var request = WebRequest.CreateHttp(string.Format(this.apiBaseUrl + userEndPoint + #"user/login.json"));
// Request header collection set up
request.ContentType = "application/json";
request.Headers.Add ("X-CSRF-Token", csrfToken);
// Add other configs
request.Method = "POST";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
string json_body_content = "{\"username\":\"" + username + "\",\"password\":\"" + password + "\"}";
streamWriter.Write(json_body_content);
streamWriter.Flush();
streamWriter.Close();
}
try{
HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse();
using (StreamReader reader = new StreamReader (httpResponse.GetResponseStream ())) {
var content = reader.ReadToEnd ();
content = content.Replace ("[],", "null,");
content = content.Replace ("[]", "null");
if (content == null) {
throw new Exception ("request_post_login - content is NULL");
} else {
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.NullValueHandling = NullValueHandling.Ignore;
JsonUser deserializedUser = JsonConvert.DeserializeObject<JsonUser>(content, jss);
if(content.Contains ("Hire company admin user")){
deserializedUser.user.roles.__invalid_name__5 = "Hire company admin user";
deserializedUser.user.roles.__invalid_name__2 = "authenticated user";
}
return deserializedUser;
}
}
}catch(Exception httpEx){
Console.WriteLine ("httpEx Exception: " + httpEx.Message);
Console.WriteLine ("httpEx Inner Exception: " + httpEx.InnerException.Message);
JsonUser JsonUserError = new JsonUser ();
JsonUserError.ErrorMessage = "Error occured: " + httpEx.Message;
return JsonUserError;
}
}
When making a Web Request using ModernHttpClient, I generally follow the pattern below. Another great library created by Paul Betts is refit, and can be used to simplify rest calls.
using (var client = new HttpClient(new NativeMessageHandler(false, false)))
{
client.BaseAddress = new Uri(BaseUrl, UriKind.Absolute);
var result = await Refit.RestService.For<IRestApi>(client).GetData();
}
The second parameter for NativeMessageHandler should be set to true if using a customSSLVerification.
Here's a look at IRestApi
public interface IRestApi
{
[Get("/foo/bar")]
Task<Result> GetMovies();
}
Number of things I had to do to get this to work.
The Self Signed Cert had to allow TLS 1.2
As the API is Drupal based, HTTPS had to be enabled on the server and a module installed to manage the HTTP specific pages.

Windows Phone sends more than one web requests in order in a call

Reccently, I am working on a project in Windows Phone. and In this project, to validate a user, I need to check at 3 web API, the logic is like below:
Step 1: access web api 1 to get the token
Step 2: access web api 2 to get the username/password by the token retrieved in Step 1
Step 3: access web API 3 to validate the user name/password in step 2
you can see we need to access those 3 API in order. as well know, window phone now access the network asynchronously, which causes a big challenge on make those API access in order, and which make the soure code hard to maintainace.
I also consider the synchronous source code like below, but I found there are some problems to access the network,many exeption will be thrown. For example, when an exception is thrown, I try to use asynchronous web request to access the same URL, it is OK. I am strugglig in it now. And I have to introduce thread to call it to avoid to block the UI thread.
internal static class HttpWebRequestExtensions
{
public const int DefaultRequestTimeout = 60000;
public static bool IsHttpExceptionFound = false;
public static WebResponse GetResponse(this WebRequest request, int nTimeOut = DefaultRequestTimeout)
{
var dataReady = new AutoResetEvent(false);
HttpWebResponse response = null;
var callback = new AsyncCallback(delegate(IAsyncResult asynchronousResult)
{
try
{
response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
dataReady.Set();
}
catch(Exception e)
{
IsHttpExceptionFound = true;
}
});
request.BeginGetResponse(callback, request);
if (dataReady.WaitOne(nTimeOut))
{
return response;
}
return null;
}
public static WebResponse PostRequest(this HttpWebRequest request, String postData, int nTimeOut = DefaultRequestTimeout)
{
var dataReady = new AutoResetEvent(false);
HttpWebResponse response = null;
var callback = new AsyncCallback(delegate(IAsyncResult asynchronousResult)
{
Stream postStream = request.EndGetRequestStream(asynchronousResult); //End the operation.
byte[] byteArray = Encoding.UTF8.GetBytes(postData); //Convert the string into a byte array.
postStream.Write(byteArray, 0, postData.Length); //Write to the request stream.
postStream.Close();
dataReady.Set();
});
request.BeginGetRequestStream(callback, request);
if (dataReady.WaitOne(nTimeOut))
{
response = (HttpWebResponse)request.GetResponse(nTimeOut);
if (IsHttpExceptionFound)
{
throw new HttpResponseException("Failed to get http response");
}
return response;
}
return null;
}
}
Any suggestion on using asynchronous web request to solve my case?
There's an example here of using asynchronous web services in a chained manner to call the Microsoft Translator service on WP7
Maybe it will give you some pointers?
http://blogs.msdn.com/b/translation/p/wp7translate.aspx

Accessing a website using C#

I'm trying to make an App for windows phone 7. This app will basiclly retrive information from a website that we use at work as our working schedule then rearrange the retrived info into a metro style UI. To be honest i don't know where to start ie. how to retrive the info. Should i use webclient class? httpwebrequest class? or something else?
All idea are appriciated
Here is a:-
Update:-
Okay either im totally stupid or there is something wrong with the code i'm writing, that i can't figure it out. I was using the same code that you wrote BUT i still get an error that a definition for Proxy is not in the System.Net.WebRequest :( This is my code (the working version):-
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
string url = "https://medinet.se/*****/schema/ibsef";
WebRequest request = WebRequest.Create(url);
request.BeginGetResponse(new AsyncCallback(ReadWebRequestCallBack), request);
}
private void ReadWebRequestCallBack(IAsyncResult callbackResult)
{
try
{
WebRequest myRequest = (WebRequest)callbackResult.AsyncState;
WebResponse myResponse = (WebResponse)myRequest.EndGetResponse(callbackResult);
using (StreamReader httpwebStreamReader = new StreamReader(myResponse.GetResponseStream()))
{
string results = httpwebStreamReader.ReadToEnd();
Dispatcher.BeginInvoke(() => parsertextBlock.Text = results);
}
myResponse.Close();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
Dispatcher.BeginInvoke(() => parsertextBlock.Text = ex.ToString());
}
}
But if i add request.Proxy=null!! i get an error, that there is no definition for Proxy in (System.Net.WebRequest). And to be honest i start getting mad of this.
Yours
/Omar
The process is called ScreenScrape and i recommend you to use Html Agility Pack http://htmlagilitypack.codeplex.com/ . Make a web service that retrieves the information from your website and rearranges to appropriate format. Use your web service by a phone and display your data.
Use WebRequest ( http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx) and WebResponse ( http://msdn.microsoft.com/en-us/library/system.net.webresponse(v=vs.100).aspx) .
TIP: Set the WebRequest.Proxy property ( http://msdn.microsoft.com/en-us/library/system.net.webrequest.proxy.aspx) to null, as i find it will be much faster.
UPDATE: More info on WebRequest Proxy property
Set Proxy = null on the WebRequest object to avoid an initial delay (that way the request won't start auto detecting proxies, which i find it's faster).
WebRequest req = WebRequest.Create("yourURL");
req.Proxy = null;
It's in the System.Net namespace so put an using statement using System.Net; or
System.Net.WebRequest req = WebRequest.Create("yourURL");
req.Proxy = null;
Regards.

WebClient NotFound error but working with HttpWebRequest/Response

In my WinPhone app I'm accessing a REST service.
At the beginnings I was using this code:
WebClient wc = new WebClient();
wc.Credentials = credentials;
wc.Headers["App-Key"] = appKey;
wc.DownloadStringCompleted +=
(o, args) => MessageBox.Show(args.Error == null ? "OK" : "Error");
wc.DownloadStringAsync(uri);
but it suddenly stopped working returning me a "The remote server returned an error: NotFound" error. After a google session and some clicks in the control panel, I didn't get it to work.
I decided to try this other way:
HttpWebRequest request = HttpWebRequest.CreateHttp(uri);
request.Credentials = credentials;
request.Headers["App-Key"] = appKey;
request.BeginGetResponse(asResult =>
{
var response = request.EndGetResponse(asResult) as HttpWebResponse;
StreamReader reader = new StreamReader(response.GetResponseStream());
string responseString = reader.ReadToEnd();
Dispatcher.BeginInvoke(
() => MessageBox.Show(response.StatusCode.ToString()));
}, null);
and it works.
I also tried to run the first snipped pointing the URI to google's home page and it works (I had to remove the credentials, of course).
Can anyone explain what's going on?
UPDATE
I managed to get it working by replacing the
wc.Credentials = new NetworkCredentials(username, password);
with
wc.Headers["Authorization"] = "Basic someBase64encodedString";
but i still wonder what happened and which are the differences between the first and the second line.
PS: the test URI is: https://api.pingdom.com/api/2.0/checks but you will need an app-key from them.
When using the Credentials property, the HttpWebRequest implementation will wait the challenge response from server before to send the 'Authorization' header value.
But this can be an issue in some cases, so you have to force Basic authentication by providing directly the Authorization header.
Example when using a REST Client library like Spring.Rest :
RestTemplate template = new RestTemplate("http://example.com");
template.RequestInterceptors.Add(new BasicSigningRequestInterceptor("login", "password"));
string result = template.GetForObject<string>(uri);

Resources