In my app i'm using Web Browser Control. And in that i'm loading a web page, which contains Cookies. The reqiurement is that i should get all the cookies and then delete it from the web page.
My code,
cookies = browserControl.GetCookies();
if (cookies.Count == 0)
{
setURL();
}
else
{
foreach (Cookie cookie in cookies)
{
bool check;
// Store the value
cookie.Discard = true;
cookie.Expired = true;
}
}
ClearCookie();
And the ClearCookie function is,
private async void ClearCookie()
{
await this.browserControl.ClearCookiesAsync();
}
But the problem is that cookies are not deleted, How can i delete the cookies in the web page loaded in Web Browser Control(browsercontrol).
Thanks in advance
If your app targets Windows Phone 8, there is a new simple API for clearing cookies: ClearCookiesAsync.
The instance of WebBrowser it's called on doesn't matter.
Sample code:
await new WebBrowser().ClearCookiesAsync();
Here is a tutorial that makes use of it: http://www.developer.nokia.com/Community/Wiki/Integrate_Facebook_to_Your_Windows_Phone_Application
Using ClearCookiesAsync function is very much straightforward, what else not clear?
await browserControl.ClearCookiesAsync();
that's the code that works to clear web browser control's cookies in your question context.
UPDATE :
Using await or not is a design decision according to your needs. If next codes need to be executed only after ClearCookiesAsync completed, then you need to add await keyword. And to be able to use await the function where it resides should be declared as async, as for example :
private async void MyFunction()
Otherwise, you can just remove await keyword, and keep your function declaration as is. Check this link or search to know more about await/async feature in new .NET framework.
Related
I currenly use a webview to load a site into a native xamarin.ios app.
public override void ViewDidLoad()
{
base.ViewDidLoad();
addressTxt.Text = "192.0.0.0";
var request = new NSMutableUrlRequest(new
NSUrl("http://test/"));
request.HttpMethod = "GET";
webview.LoadRequest(request);
}
This loads the site correctly into the webview. But i need to grab a hidden field value from the page for use within the app. Is there any i can do this?
I've seen a few examples, but nothing for xamarin.ios.
Thanks
You need to evaluate JavaScript returning needed field to get value from page in UIWebView.
string result = _webViewInstance.EvaluateJavascript(yourJavaScriptCode);
also you can see this answer WKWebView evaluate JavaScript return value
I wrote a HttpModule to intercept, evaluate and authorize requests, checking if logged user has appropriate access to the url being requested, in a pretty old legacy system written in ASP.NET 2.0(Web pages, not Web app), whose customer does not want to port to a newer framework. Restrictions have been loaded and cached at login time.
Everything works fine, except when some page contains an <asp:MultiView> component or when there is a button that launch an ajax method. When one of these situations occur, and user doesn't have rights to access that url, an alert box pops up with an "Unknown error" message, that came from a ThreadAbortException thrown by Response.End() method.
The question is: Why does my "Unauthorized" message is being overwritten by "Unknown Error" from the exception, only on these two situations?
Is there a way of doing an Url Authorization system, using database and caching and without cluttering Web.config with roles like those older ASP.NET samples?
// My module init method.
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
// PreRequestHandlerExecute is the first stage at ASP.NET Pipeline
// where we could get a fulfilled Session variable
}
private void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
// additional request filtering/validation/etc.
LoggedUser user = (LoggedUser)application.Session["user"];
string path = context.Request.Path;
// more checks and rules...
if (!checkUserAuthorization(path, user))
{
context.Response.Write("<script>alert('Unauthorized. Contact your manager.');</script>");
context.Response.Write("<script>window.history.back();</script>");
context.Response.StatusCode = 403;
context.Response.End();
}
}
EDIT: What I've already tried (with no goal):
Response.OutputStream.Close();
Response.Flush();
HttpApplication.CompleteRequest();
it's by design. you must ignore it and add a catch for that exception.
try {
context.Response.End();
}
catch{}
Foreword
After a lot of research, finally I got it. Considering ASP.NET 2.0, concerning AJAX operations, the project I'm working uses a Microsoft component called "Atlas", which in turn got renamed to ASP.NET AJAX. At the time this system was written, the developers used the beta ASP.NET AJAX (codename "Atlas") to address all ajax and partial rendering needs.
I needed to dig deeper in source code (thanks to Reflector), to understand and inspect from where does that "Unknown Error" comes.
Inside the Microsoft.Web.Atlas, there is a file named Microsoft.Web.Resources.ScriptLibrary.*.Atlas.js (where * could be Debug or Release) which is rendered at runtime through a WebResource.axd "proxy".
This javascript file have a bug, because it expects to ASP.NET request always return an HTTP 200 (OK) response code, which in my code it's not happening (I'm returning a 403 Forbidden code at my module).
Code
From Microsoft.Web.Resources.ScriptLibrary.*.Atlas.js taken from WebResource.axd:
this._onFormSubmitCompleted = function(sender, eventArgs) {
var isErrorMode = true;
var errorNode;
var delta;
if (sender.get_statusCode() == 200) {
delta = sender.get_xml();
if (delta) {
errorNode = delta.selectSingleNode("/delta/pageError");
if (!errorNode) {
isErrorMode = false;
}
}
}
if (isErrorMode) {
if (errorNode) {
pageErrorMessage = errorNode.attributes.getNamedItem('message').nodeValue;
}
else {
pageErrorMessage = 'Unknown error';
}
this._enterErrorMode(pageErrorMessage);
return;
}
// Code continues.
}
From this code, we can see that since response code is not an 200 OK, that errorNode variable won't be set, and this if (errorNode) statement will always be false.
In this case, I was left with two options: Always return HTTP 200 and modify all pages that have an <atlas:ScriptManager> with and add an ErrorTemplate tag on each, or supersede that script with one that consider non-HTTP 200 responses, loading it below </form> tag at the Master page.
There is a lot of tutorials on how to do a proper error handling when using ScriptManager and UpdatePanels (an official one here), by subscribing to the AsyncPostBackError event), but this beta version (Atlas) simply don't have this event.
I have a .net console application that I want to use to pull Instagram posts via the Instasharp wrapper using a hashtag search.
I use C# .net web forms extensively and am not very familiar with MVC nor how to use the await keyword. The code sample below seems to run, but never provides any output.
This line:
var tagInfo = await tagApi.Get("soccer");
Returns me to the calling method with no indication of retrieved data.
Can anyone provide insights as to what I am doing wrong here?
public static async void GetInstagram(String tag, InstagramConfig config)
{
var instagramPosts = await LoadInstagramPosts(tag, config);
dynamic dyn = JsonConvert.DeserializeObject(instagramPosts.ToString());
foreach (var data in dyn.data)
{
Console.WriteLine("{0} - {1}", data.filter, data.images.standard_resolution.url);
}
}
public static async Task<TagResponse> LoadInstagramPosts(String hashTagTerm, InstagramConfig config)
{
var tagApi = new InstaSharp.Endpoints.Tags(config);
var tagInfo = await tagApi.Get("soccer");
}
EDITED code after first comment which solved my initial problem.
I feel like I'm close but something is still missing.
See specific questions below...
I've based the code on the documentation from InstaSharp GitHub (https://github.com/InstaSharp/InstaSharp). GitHubs example is based on an MVC application, mine is not an MVC project, but a console application.
I feel like I am very close and maybe others will benefit from helping me solve this.
My specific questions...
1) Not sure where the 'code' parameter in the OAuth method originate??
2) How to perform the needed call backs with Instagram??
var config = new InstaSharp.InstagramConfig(location.InstagramClientId, location.InstagramClientSecret, "http://localhost");
string instagramLoginLink = InstagramLogin(config);
GetInstagram("soccer", config, instagramLoginLink);
public static async void GetInstagram(String tag, InstagramConfig config, string code)
{
OAuthResponse oAuthResponse = await OAuth(code, config);
var instagramPosts = await LoadInstagramPosts(tag, config, oAuthResponse);
if(instagramPosts.Data != null)
{
dynamic dyn = JsonConvert.DeserializeObject(instagramPosts.Data.ToString());
foreach (var data in dyn.data)
{
Console.WriteLine("{0} - {1}", data.filter, data.images.standard_resolution.url);
}
}
}
public static string InstagramLogin(InstagramConfig config)
{
var scopes = new List<OAuth.Scope>();
scopes.Add(InstaSharp.OAuth.Scope.Likes);
scopes.Add(InstaSharp.OAuth.Scope.Comments);
string link = InstaSharp.OAuth.AuthLink(config.OAuthUri + "authorize", config.ClientId, config.RedirectUri, scopes, InstaSharp.OAuth.ResponseType.Code);
return link;
}
public static async Task<OAuthResponse> OAuth(string code, InstagramConfig config)
{
// add this code to the auth object
var auth = new OAuth(config);
// now we have to call back to instagram and include the code they gave us
// along with our client secret
return await auth.RequestToken(code);
}
public static async Task<TagResponse> LoadInstagramPosts(String hashTagTerm, InstagramConfig config, OAuthResponse OAuth)
{
var tagApi = new InstaSharp.Endpoints.Tags(config, OAuth);
return await tagApi.Get("soccer");
}
I'm a bit late to the show, yet probably my answer will help someone who find this question when googling, someone like me.
The main problem with your approach is that Instagram is using OAuth authentication. I suggest you to google on OAuth to understand the principles, but I will try to explain the practical points of it below.
OAuth approach means that the result of the InstagramLogin method in the snippet above is not the code. It's the link where you need to send you user (yes, using a browser or a web-view) so that they can sign into their Instagram account and then authorize your application to access their data (so-called user consent screen).
In the end, after user consent, Instagram will redirect browser to the URL of your choice (it should be previously added in the list of allowed redirect urls in Instagram API -> Manage Clients (top-right corner) -> Create/Select client to Manage -> Security tab)
You can try set a breakpoint and copy the value of instagramLoginLink into your browser's address box. You will be able to see the whole flow of authentication and consent - and finally the redirect url that will most probably produce 404 in your browser.
This final link will contain the code in a get parameter. It's the so-called grant code that allows you to get an access token. This code is to be extracted from url and then used in your call to OAuth.RequestToken).
PS: Yes, everything I say above means that you need either a web app running that will redirect user to Instagram or a client-side app that will show the user a web view and somehow handle the moment when Instagram sends the user back to your redirect url - to grab the code and proceed.
I'm coding an iPhone app with a UIWebView, in Xamarin using C#.
By default embedded links within the web view open a web page in that same web view. I would instead like them to launch the linked page in a new safari browser instance.
This has been answered for objective C in X-Code but as far as I can see not for Xamarin C#
webView.LoadHtmlString(html, new NSUrl(Const.ContentDirectory, true));
Thanks in advance
Adam
You can open a web page in the brower of the device (Safari) with this command.
UIApplication.SharedApplication.OpenUrl(new NSUrl("www.google.com"));
You don't have to use UIWebView at all. If you want to open some web pages in UIWebView and some with Safari you need to implement the ShouldStartLoad delegate. Here you can determine whether to open the web page in UIWebView or rather in Safari.
private bool HandleShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType)
{
// you need to implement this method depending on your criteria
if (this.OpenInExternalBrowser(request))
{
// open in Safari
UIApplication.SharedApplication.OpenUrl(request.Url);
// return false so the UIWebView won't load the web page
return false;
}
// this.OpenInExternalBrowser(request) returned false -> let the UIWebView load the request
return true;
}
At last somewhere in ViewDidLoad (or other place where you initiliaze the WebView) add the following code.
webView.ShouldStartLoad = HandleShouldStartLoad;
If loading content into a UIWebView and you want to use Safari to open links, doing it the way described above will get you a blank page. You need to check the NavigationType.
private bool HandleShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navType)
{
if (navType == UIWebViewNavigationType.LinkClicked)
{
UIApplication.SharedApplication.OpenUrl(request.Url);
return false;
}
return true;
}
The easiest/simplest way to do it is to assign a delegate to the UIWebView's ShouldStartLoad property:
webView.ShouldStartLoad = (w, urlRequest, navigationType) => {
// Open the url in Safari here.
// The urlRequest parameter is of type NSUrlRequest, you can get the URL from it.
return false; //return true for urls you actually want your web view to load.
};
Make sure the delegate returns false, for the links you want to load in Safari, so that your UIWebView does not load the link.
I'm using the Yahoo Uploader, part of the Yahoo UI Library, on my ASP.Net website to allow users to upload files. For those unfamiliar, the uploader works by using a Flash applet to give me more control over the FileOpen dialog. I can specify a filter for file types, allow multiple files to be selected, etc. It's great, but it has the following documented limitation:
Because of a known Flash bug, the Uploader running in Firefox in Windows does not send the correct cookies with the upload; instead of sending Firefox cookies, it sends Internet Explorer’s cookies for the respective domain. As a workaround, we suggest either using a cookieless upload method or appending document.cookie to the upload request.
So, if a user is using Firefox, I can't rely on cookies to persist their session when they upload a file. I need their session because I need to know who they are! As a workaround, I'm using the Application object thusly:
Guid UploadID = Guid.NewGuid();
Application.Add(Guid.ToString(), User);
So, I'm creating a unique ID and using it as a key to store the Page.User object in the Application scope. I include that ID as a variable in the POST when the file is uploaded. Then, in the handler that accepts the file upload, I grab the User object thusly:
IPrincipal User = (IPrincipal)Application[Request.Form["uploadid"]];
This actually works, but it has two glaring drawbacks:
If IIS, the app pool, or even just the application is restarted between the time the user visits the upload page, and actually uploads a file, their "uploadid" is deleted from application scope and the upload fails because I can't authenticate them.
If I ever scale to a web farm (possibly even a web garden) scenario, this will completely break. I might not be worried, except I do plan on scaling this app in the future.
Does anyone have a better way? Is there a way for me to pass the actual ASP.Net session ID in a POST variable, then use that ID at the other end to retrieve the session?
I know I can get the session ID through Session.SessionID, and I know how to use YUI to post it to the next page. What I don't know is how to use that SessionID to grab the session from the state server.
Yes, I'm using a state server to store the sessions, so they persist application/IIS restarts, and will work in a web farm scenario.
Here is a post from the maintainer of SWFUpload which explains how to load the session from an ID stored in Request.Form. I imagine the same thing would work for the Yahoo component.
Note the security disclaimers at the bottom of the post.
By including a Global.asax file and the following code you can override the missing Session ID cookie:
using System;
using System.Web;
public class Global_asax : System.Web.HttpApplication
{
private void Application_BeginRequest(object sender, EventArgs e)
{
/*
Fix for the Flash Player Cookie bug in Non-IE browsers.
Since Flash Player always sends the IE cookies even in FireFox
we have to bypass the cookies by sending the values as part of the POST or GET
and overwrite the cookies with the passed in values.
The theory is that at this point (BeginRequest) the cookies have not been ready by
the Session and Authentication logic and if we update the cookies here we'll get our
Session and Authentication restored correctly
*/
HttpRequest request = HttpContext.Current.Request;
try
{
string sessionParamName = "ASPSESSID";
string sessionCookieName = "ASP.NET_SESSIONID";
string sessionValue = request.Form[sessionParamName] ?? request.QueryString[sessionParamName];
if (sessionValue != null)
{
UpdateCookie(sessionCookieName, sessionValue);
}
}
catch (Exception ex)
{
// TODO: Add logging here.
}
try
{
string authParamName = "AUTHID";
string authCookieName = FormsAuthentication.FormsCookieName;
string authValue = request.Form[authParamName] ?? request.QueryString[authParamName];
if (authValue != null)
{
UpdateCookie(authCookieName, authValue);
}
}
catch (Exception ex)
{
// TODO: Add logging here.
}
}
private void UpdateCookie(string cookieName, string cookieValue)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookieName);
if (cookie == null)
{
HttpCookie newCookie = new HttpCookie(cookieName, cookieValue);
Response.Cookies.Add(newCookie);
}
else
{
cookie.Value = cookieValue;
HttpContext.Current.Request.Cookies.Set(cookie);
}
}
}
Security Warning: Don't just copy and paste this code in to your ASP.Net application without knowing what you are doing. It introduces security issues and possibilities of Cross-site Scripting.
Relying on this blog post, here's a function that should get you the session for any user based on the session ID, though it's not pretty:
public SessionStateStoreData GetSessionById(string sessionId)
{
HttpApplication httpApplication = HttpContext.ApplicationInstance;
// Black magic #1: getting to SessionStateModule
HttpModuleCollection httpModuleCollection = httpApplication.Modules;
SessionStateModule sessionHttpModule = httpModuleCollection["Session"] as SessionStateModule;
if (sessionHttpModule == null)
{
// Couldn't find Session module
return null;
}
// Black magic #2: getting to SessionStateStoreProviderBase through reflection
FieldInfo fieldInfo = typeof(SessionStateModule).GetField("_store", BindingFlags.NonPublic | BindingFlags.Instance);
SessionStateStoreProviderBase sessionStateStoreProviderBase = fieldInfo.GetValue(sessionHttpModule) as SessionStateStoreProviderBase;
if (sessionStateStoreProviderBase == null)
{
// Couldn't find sessionStateStoreProviderBase
return null;
}
// Black magic #3: generating dummy HttpContext out of the thin air. sessionStateStoreProviderBase.GetItem in #4 needs it.
SimpleWorkerRequest request = new SimpleWorkerRequest("dummy.html", null, new StringWriter());
HttpContext context = new HttpContext(request);
// Black magic #4: using sessionStateStoreProviderBase.GetItem to fetch the data from session with given Id.
bool locked;
TimeSpan lockAge;
object lockId;
SessionStateActions actions;
SessionStateStoreData sessionStateStoreData = sessionStateStoreProviderBase.GetItem(
context, sessionId, out locked, out lockAge, out lockId, out actions);
return sessionStateStoreData;
}
You can get your current SessionID from the following code:
string sessionId = HttpContext.Current.Session.SessionID;
Then you can feed that into a hidden field maybe and then access that value through YUI.
It's just a get, so you hopefully won't have any scaling problems. Security-problems though, that I don't know.
The ASP.Net Session ID is stored in Session.SessionID so you could set that in a hidden field and then post it to the next page.
I think, however, that if the application restarts, the sessionID will expire if you do not store your sessions in sql server.