Post using default browser in wpf - c#

I have an application that simulates a post to a web page with post data using the WebBrowser class in a wpf application.
private void openBrowser(CreateDdiRequest postData)
{
string serialisedObject = serializeValues(postData);
string postHeaders = "Content-Type: application/x-www-form-urlencoded";
_browser.Navigate(new Uri(_url), "_blank", Encoding.UTF8.GetBytes(serialisedObject), postHeaders);
}
This opens up the IE web browser and pushes the post data to the site.
Problem I have now is that I want it to open the default browser not IE.
Is there anyway to achieve this?

As far as I know, the browser that will be launched is not always the default one.
Follow these steps :
1° Despending of your Windows version, you should search "Default Programs" on the start menu, or in the settings for Windows 8. Well, Search for the "Default Programs" panel in your computer :)
2° Enter Default programs, and then tap or click Default Programs.
3° Tap or click Set your default programs.
4° Select your browser from the list of programs. As you can (maybe) see, the browser is not default for every possible actions ("The program has 15 out of 20 defaults")
5° Tap or click Set this program as default, and then tap or click OK.
If it's not working, try to launch your browser by its path :
Process.Start(#"%AppData%..\Local\Google\Chrome\Application\chrome.exe",
"http:\www.YourUrl.com");
Of course, it's working for an external URL, maybe not for what you want.
By the way, if you just want to do a POST request, you don't need the webbrowser class.
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{ "thing1", "hello" },
{ "thing2", "world" }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("http://www.example.com/recepticle.aspx", content);
var responseString = await response.Content.ReadAsStringAsync();
}
Sources :
HTTP request with post
http://windows.microsoft.com/en-US/internet-explorer/make-ie-default-browser#ie=ie-11
How to launch a Google Chrome Tab with specific URL using C#

To launch the default browser, simply call Process.Start() and pass the form values in the URL.
Process.Start(myUrl)

Related

Logging in in embedded browser deprecation

Facebook is terminating logging in via embedded browser. I have implemented FB login using CustomRenderer in Xamarin.Forms.
In that we do not have option of LoginBehavior. So does anyone know how to handle this in Xamarin.Forms?
The best solution is to open the login page in a CustomTab, Android offers such tabs so one does not have to call an external browser (I don't know whether Xamarin offers its own classes to use OAuth).
public void OpenWebsiteInApp(string url)
{
// Use the Android custom tabs to display the webpage inside the app.
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.Build();
customTabsIntent.LaunchUrl(_applicationContext, Uri.Parse(url));
}
To catch the redirect from the online service, you need to implement an activity with an IntentFilter defining a DataScheme.
Finally I have got the solution for Xamarin.Forms. I have followed this tutorial and the problem is solved.
https://evgenyzborovsky.com/2018/03/09/using-native-facebook-login-button-in-xamarin-forms/
After successful login we are getting Access_token and userid values and by using it we can get user details like First name, Last name easily.
Here is the code for the same:
var client = new System.Net.Http.HttpClient();
var url = $"https://graph.facebook.com/{facebookResponse.userId}?
fields=id,first_name,last_name,email,picture&access_token=
{facebookResponse.accessToken}";
var response = await client.GetAsync(url);
var result = response.Content.ReadAsStringAsync().Result;
var resultobject = JsonConvert.DeserializeObject<FacebookResponse>(result);
Limitations:
You can not change Login button Icon or Text properties like font and size etc.
If you want to use another FB account to login you first have to logout from device's browser manually.

Close webview xamarin forms

I have implement payment method with return URL and using webview open URL with my app. Recent, I'am issue want auto close webview with response success or fail process payment.
I encountered this case. Here is the solution I found.
After creating the WebElement, we bind the Navigating event to a certain method.
MyPage.Source = link;
MyPage.Navigating += Webview_Navigating;
MyPage WebElment name.
link is my link address
.
Then we perform our transactions here.
private void Webview_Navigating(object sender, WebNavigatingEventArgs e)
{
var url = e.Url;
if (url.Contains("status=1"))
{
int ordID = 0;
//save order
}
}
For me, if the changed link address checkout status=1, the checkout is successful.
You need to call Url property in WebNavigatingEventArgs to catch the changed url
If useful, choose. Good Luck
Sure! You can get response form WebView.
I recommend you use HybridWebView (see: https://github.com/devsmadeofsteel/Plugin.HybridWebView) as alternative.
Examples:
In Xamarin page, create a browser add register a named callback, and add browser to page childs
HybridWebViewControl Browser = new HybridWebViewControl();
//You can load browser content by string or URL, here is string which you can hard code or store in resource files
Browser.ContentType = Plugin.HybridWebView.Shared.Enumerations.WebViewContentType.Internet;
Browser.Source = YourUrl;
Browser.AddLocalCallback(YourCallBackFunctionName, CallBackFunction);
When run, HybridWebViewControl will insert a function with the name you specified in
YourCallBackFunctionName, and the single parameter is string type. So, In JavaScript of the page loaded by YourUrl, you can call back with the specified CallBackFunctionName:
function AnyFunction() {
//...
YourCallBackFunctionName(YourStringParameter);
}
When you call YourCallBackFunctionName(YourStringParameter) in JavaScript, you can get YourStringParameter in CallBackFunction using C#.
So, you could define different CallBackFunctions or pass different parameters with single CallBackFunction, to control the HybridWebView and the page or view which contain it, such as hide HybridWebView or close the page.
Have a try!

Set Current culture in url when application starts or navigates to home page

I am working on a small web application (Razor Pages) and I have added localization to it. The problem I have now is the following:
When application loads first time or when user presses home button (<a href="/"</a>), the url in the browser is this:
https://localhost/
and when I press a link (<a asp-page="/login"></a>) it navigates me to https://localhost/login instead of https://localhost/{currentCulture}/login
and for this reason, I want to it to be something like this:
https://localhost/{currentCulture}/
For example, for english --> https://localhost/en/
I have already set default current culture and it is applied when application starts but it is not written in the url.
I have followed this tutorial to add localization to my app : http://www.ziyad.info/en/articles/10-Developing_Multicultural_Web_Application
Update:
When User presses home button I did this: and it works.
I do not know how good solution it is, but you can solve this problem so:
Create a class and implement Microsoft.AspNetCore.Rewrite.IRule:
public class FirstLoadRewriteRule : IRule
{
public void ApplyRule(RewriteContext context)
{
var culture = CultureInfo.CurrentCulture;
var request = context.HttpContext.Request;
if(request.Path == "/")
{
request.Path = new Microsoft.AspNetCore.Http.PathString($"/{culture.Name}");
}
}
}
In your app request.Path == "/" will be true only when app loads first time (when you press home, request.path is "/en" {for English}). So, default culture name will be added to the url. You will not see it in url when app loads, but when you press (<a asp-page="/login"></a>), you will see that you are redirected to https://localhost/en/login.
You have to register this rule in startup.cs in Configure method:
var options = new RewriteOptions().Add(new FirstLoadRewriteRule());
app.UseRewriter(options);

Spotify authorization code flow (WPF browser control) C#

I'm using Spotify account service (authorization code flow) to get an authorization code by passing in the required parameters (client_id, response_type and redirect_uri. Its a WPF application so i am using the browser control and navigating the user to
https://accounts.spotify.com/authorize/?client_id=myclientId&response_type=code&redirect_uri=someUri
When i copy paste the link in the browser, i see the right stuff i.e page with the Login to Spotify button but when i am navigating through the browser control in my WPF application, it gives me a file download dialog with Authorize.json file to download with Open and Save options, however in some cases it presents the right page to browser code.
Below is my code:
public winOAuthBrowserForm(string navigateTo)
{
InitializeComponent();
webBrowser.Navigated += webBrowser_Navigated;
webBrowser.Navigate(navigateTo);
}
private void webBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
if(!String.IsNullOrEmpty(e.Uri.Query))
{
//since we are looking for code for authorization that will be exchanged for request token from the server
if (e.Uri.Query.StartsWith("?code=") || e.Uri.Query.Contains("code="))
{
code = HttpUtility.ParseQueryString(e.Uri.Query).Get("code");
this.Close();
}
if (e.Uri.Query.StartsWith("?error=") || e.Uri.Query.Contains("error="))
{
error = HttpUtility.ParseQueryString(e.Uri.Query).Get("error");
this.Close();
}
}
}
And i am calling this control like:
var uri = string.Format(SpotifyAuthUriFormatter, RequestAuthBaseUrl, clientId);
winOAuthBrowserForm form = new winOAuthBrowserForm(uri);
form.ShowDialog();
This is what i see:
UPDATE: When i right click on document and see the properties, i see it changes the URL to something like res://ieframe.dll/navcancl.htm#... I've searched it and found some solutions related to I.E (I'm using latest but you can't be sure that it'll be latest on client machines), some say that its firewall setting. The thing is, it appears sometimes only.
Any ideas? Thanks

Grabbing Cookies in Web Browser Control - WP7

In order to log into a certain part of a website the users of my application require their cookie. To do this I need to grab it and pass it to url.
Does anyone know how to grab a certain websites cookie from the browser control?
I saw this method but wasn't quite clear.
Thanks, TP.
As of WP 7.1 Mango "release", if one may call it, please see the WebBrowser Control Overview for Windows Phone. It has been recently updated a little bit, and it turns out that they actually have added some support for cookie-retrieval from the WebBrowser. On the bottom of the page you will find a tiny link GetCookies(WebBrowser) pointing to description of a new class: WebBrowserExtensions with this very handy method. Yes, this class has only that one single member. It's an extension method, I suppose no explanations needed on that.
I have not played with this method much, but it seems that this will allow you to access the very same thing as the JS trick: the cookieset for the current URL. It probably will not allow to set anything, nor to peek cookies for other URLs. Maybe if you play hard with the CookieContainer you will receive, but I doubt.
On the 7.0 release, I've been struggling quite hard to achieve "cookie transparency" for my App. Long story short, my app was doing some background HTTP requests, and also had a WebBrowser to show some online content -- and "it would be great" if both sources of connections would emit the same cookies to the server.. And guess what, my application had to make the first request, then let the browser navigate. With such requirements, there was virtually is no way to achieve consistency of the cookies - bah, even with the current new and glorious GetCookie method, I suppose it would be damn hard. So, to the point - it was possible, but needed to use some hidden API, that is present publicitly on the Phone, but is hidden in the SDK. The API is available the (public) class System.Net.Browser.WebRequestCreator, freely available. The quirk is: in the SDK this class has a single public static property "IWebRequestCreate ClientHttp" with a method "Create" that you can use to "factory" your "raw http" connections - in case you dont want to use the WebClient for some reason. On the phone, and on the emulator, there is a second public static property called "IWebRequestCreate BrowserHttp", easily returned by Reflection:
PropertyInfo brwhttp = typeof(System.Net.Browser.WebRequestCreator)
.GetProperty("BrowserHttp")
with this property, you will be able to obtain a "special" internal instance of IWebRequestCreate that is used internally by the WebBrowser. By opening your background HTTP requests with this class, you will get your cookies automatically set as if they were created/sent by the WebBrowser control, but in turn - you will NOT be able to modify http headers, userprovide http user authentication and neither do a few lowlevel things - because all that settings will be synced with the WebBrowser's data stored for current 'system user instance', if I'm allowed to call it as such on the single-user Phone device heh. The interoperation between connections and the WebBrowser works both ways - if your HTTP connection (created with use of the 'hidden property') receives any settings/cookies/etc -- then the WebBrowser will instantly notice them and update its own cache. No cookie/session loss on neither of the sides!
If you need to passively get cookies for your subsequent connections after some first WebBrowser navigation - please use the GetCookie or the JS way.
But if you need your code to be first, and then pass authz to the WebBrowser -- you will probably have to dig deeper and use the above.. It's been hidden, so please resort to the other means first!
..and don't ask me how did I found it or how much time it took :P
have a nice fun with it
//edit: I've just found out, that the BrowserHttp property is a normal Silverlight's way to access the Browser's connection factory, please see BrowserHttp. It seems that it is only has been hidden in the 'miniSilverlight' written for the WP7 platform!
The approach being described in the post you linked is to use the WebBrowser control's InvokeScript method to run some javascript. However the post appears to use a "cookies" collection which doesn't actually exist.
string cookie = myWebBrowser.InvokeScript("document.cookie") as string;
Now for the hard part the string you get contains all pertinent cookie name/value pairs for the page with the values still being Url encoded. You will need to parse the returned string for the value you need.
See document.cookie property documentation.
Edit:
Looking at it fresh instead of relying on the post, InvokeScript invokes named function on the window of the host browser. Hence the page being displayed in the WebBrowser would itself need to include a function like:-
function getCookie() { return document.cookie; }
Then the InvokeScript would look like:-
string cookie = myWebBrowser.InvokeScript("getCookie");
As #quetzalcoatl already suggested, you can use internal instance of WebRequestCreator to share cookies between browser instances and instances of WebRequest. You don't get to access the cookies directly though, I think that's just a security measure by Microsoft.
This code below creates a WebReqeust object, connected to CookieContainer of WebBrowser instance. It then posts to a url to log in the user and store cookies in the container.
After it's done, all browser instances within the app instance will have required set of cookies.
var browser = new WebBrowser();
var brwhttp = typeof (WebRequestCreator).GetProperty("BrowserHttp");
var requestFactory = brwhttp.GetValue(browser, null) as IWebRequestCreate;
var uri = new Uri("https://www.login.com/login-handler");
var req = requestFactory.Create(uri);
req.Method = "POST";
var postParams = new Dictionary<string, string> {
{"username", "turtlepower"},
{"password": "ZoMgPaSSw0Rd1"}
};
req.BeginGetRequestStream(aReq => {
var webRequest = (HttpWebRequest)aReq.AsyncState;
using (var postStream = webRequest.EndGetRequestStream(aReq)) {
// Build your POST request here
var postDataBuilder = new StringBuilder();
foreach (var pair in paramsDict) {
if (postDataBuilder.Length != 0) {
postDataBuilder.Append("&");
}
postDataBuilder.AppendFormat("{0}={1}", pair.Key, HttpUtility.UrlEncode(pair.Value));
}
var bytes = Encoding.UTF8.GetBytes(postDataBuilder.ToString());
postStream.Write(bytes, 0, bytes.Length);
}
// Receive response
webRequest.BeginGetResponse(aResp => {
var webRequest2 = (HttpWebRequest) aResp.AsyncState;
webRequest = (HttpWebRequest)aResp.AsyncState;
string resp;
using (var response = (HttpWebResponse)webRequest2.EndGetResponse(aResp)) {
using (var streamResponse = response.GetResponseStream()) {
using (var streamReader = new System.IO.StreamReader(streamResponse)) {
resp = streamReader.ReadToEnd();
}
}
}
}, webRequest);
}, req);
One of the issues I couldn't solve though was exceptions thrown when server returns 302 - it seems to throw WebException error with "Not found" description.
// Ensure this is set to true BEFORE navigating to the page
webBrowser1.IsScriptEnabled = true;
// Once the page has loaded, you can read the cookie string
string cookieString = webBrowser1.InvokeScript("eval", new string[] { "document.cookie;" }) as string;
The cookieString variable will contain the full cookie for the document. You can then parse the string.
There is an WebBrowser Extension class which is exactly developed for this:
CookieCollection tempCookies = Microsoft.Phone.Controls.WebBrowserExtensions.GetCookies(this.BrowserControl);

Categories