i have a WebForms application, and am trying to use the uploadify jquery library.
It works fine in IE8, but doesn't in FF7, FF10, or FF3. The break point i put in Upload.ashx is not hit.
I did quite the search and found that it has to does with cookies, something like ASPXAUTH. I tried adding it to 'scriptData', but no success.
Any ideas?
Page code:
<script type="text/javascript">
$(document).ready(function () {
alert($(".hidcook").val());
// <![CDATA[
var id = "55";
var theString = "asdf";
$('#fileInput').uploadify({
'uploader': 'uploadify/uploadify.swf',
'script': 'Upload.ashx',
'scriptData': { 'id': id, 'foo': theString },
'cancelImg': 'uploadify/cancel.png',
'auto': true,
'multi': true,
'fileDesc': 'All Files',
'queueSizeLimit': 90,
'buttonText': 'Importar Planilha',
'folder': '/uploads',
'onAllComplete': function (event, queueID, fileObj, response, data) {
}
});
});
// ]]></script>
Upload.ashx:
public class Upload : IHttpHandler, IRequiresSessionState{
public void ProcessRequest(HttpContext context)
{
try
{
HttpPostedFile file = context.Request.Files["Filedata"]; //breakpoint
int id = (Int32.Parse(context.Request["id"]));
string foo = context.Request["foo"];
file.SaveAs("C:\\" + id.ToString() + foo + file.FileName);
context.Response.Write("1");
}
catch (Exception ex)
{
context.Response.Write("0");
}
}
If your website content is not public, add to web.config authorization access to the Handler.
<location path="Upload.ashx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
There are some differences in how browsers implement file upload through flash component.
IE uses the same session. FF opens a new connection, so the server sees an un-authenticaded user that is trying to access a protected page.
I had an issue using MVC where uploadify didn't post to the controller action.
It was due to an authentication issue. Flash for some reason creates it's own separate cookie to the browser, so if the user has already been authenticated with the browser (ASPXAUTH) cookie, and then the swf file makes a separate request using it's own flash cookie (which has not been authenticated.
Run fiddler to see whats happening, you may find that the server request that the uploadify is making is being redirected to the login.aspx page.
Although I don't know why this would work in just IE?
Related
I am using ASP.NET MVC (latest version).
Imagine having 2 pages:
Page-1: "Enter data" >> Page-2: "Thank you"
After submitting Page-1 you are being redirected to Page-2.
My goal: I want to make sure that you can't go back to Page-1 when you hit the browser's back button once you made it to Page-2. Instead I want you rather to stay on Page-2 (or being pushed forward to Page-2 every time you hit the back button).
I have tried all different kind of things. The following is just some simplified pseudo code ...
[NoBrowserCache]
public ActionResult Page1(int userId)
{
var user = GetUserFromDb(userId);
if (user.HasAlreadySubmittedPage1InThePast)
{
// forward to page 2
return RedirectToAction("Page2", routeValues: new { userId = userId });
}
var model = new Page1Model();
return View("Page1", model);
}
[NoBrowserCache]
[HttpPost]
public ActionResult Page1(Page1Model model)
{
var user = GetUserFromDb(model.UserId);
if (user.HasAlreadySubmittedPage1InThePast)
{
// forward to page 2
return RedirectToAction("Page2", routeValues: new { userId = model.UserId });
}
// Save posted data to the db
// ...
return RedirectToAction("Page2", routeValues: new { userId = model.UserId });
}
public class NoBrowserCache : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Haha ... tried everything I found on the web here:
// Make sure the requested page is not put in the browser cache.
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.SetNoStore();
filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-cache");
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.Now);
filterContext.HttpContext.Response.Expires = 0;
}
}
If only I could make sure that a request is being sent to the server every time I hit the back button. But right now, clicking the back button just pulls Page-1 from my browser's cache without sending a request to the server. So currently, I have no chance to redirect you forward to Page-2 by server means.
Any ideas or suggestions?
Thanks, guys!
Btw: There is no login/authentication involved. So, I can't use Session.Abandon() or stuff like this. And I would rather use some server based code than javascript if possible.
EDIT 2017-5-12
Following #grek40, I made sure that the anti-chaching statements end up in the browser. I therefor completely removed the [NoBrowserCache]-ActionFilterAttribute from my C# code above. Instead I added the following statements in the <head> section of my _Layout.cshtml:
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
I confirm that these three lines are being rendered to my browser (used my browser's developer tools to inspect). However, caching still works. I can still move backward without any server requests. Tested this with Google Chrome v62, Firefox Quantum v57 and Microsoft Edge v41 (all on Win10). #
EDIT 2017-6-12
Again following #grek40's suggestions: tried Expires: 0 as well as Expires: -1. No difference. I still didn't manage, to turn off my browser's cache.
Finally I found a solution. It's javascript based, but very simple.
I just had to add the following snippet to my Page-2 (the page I don't want users to leave anymore once they got there):
<script type="text/javascript">
$(document).ready(function () {
history.pushState({ page: 1 }, "title 1", "#nbb");
window.onhashchange = function (event) {
window.location.hash = "nbb";
};
});
I found this here: how to stop browser back button using javascript
Thanks to all your support guys. But "my own" solution was the only one that worked.
This can be done by using javascript. Use the following code
<script type = "text/javascript" >
function preventBack(){window.history.forward();}
setTimeout("preventBack()", 0);
window.onunload=function(){null};
</script>
or check the following link1 and link2.
This little piece of code might help you in solving your issue.
<script type="text/javascript">
/*To retain on the same view on Back Click*/
history.pushState(null, null, window.location.href);
window.addEventListener('popstate', function (event) {
history.pushState(null, null, window.location.href);
event.preventDefault();
});
</script>
You can add a line of javascript to every page for a client-side solution:
history.forward();
See docs on MDN. When there is a page to go forward to (which is when the used pressed the BACK button), this will force the user to that page. When the user already is at the most recent page, this does nothing (no error).
Response.Cache.SetCacheability(HttpCacheability.NoCache); // HTTP 1.1.
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
Response.AppendHeader("Expires", "0"); // Proxies.
I have run into an issue recently where we have been told to remove the hash symbols from our Backbone applications. This presents two problems: (a) the ASP.NET routes need to handle any remotely linked URL (currently this is no problem with the hash symbols) so that we're not hitting a 404 error and (b) the proper route needs to be preserved and passed on to the client side (Backbone) application. We're currently using ASP.NET MVC5 and Web API 2 for our backend.
The setup
For an example (and test project), I've created a test project with Backbone - a simple C# ASP.NET MVC5 Web Application. It is pretty simple (here is a copy of the index.cshtml file, please ignore what is commented out as they'll be explained next):
<script type="text/javascript">
$(document).ready(function(event) {
Backbone.history.start({
//pushState: true,
//root: "/Home/Index/"
});
var Route = Backbone.Router.extend({
routes: {
"test/:id": function (event) {
$(".row").html("Hello, " + event);
},
"help": function () {
alert("help!");
}
}
});
var appRouter = new Route();
//appRouter.navigate("/test/sometext", { trigger: true });
//appRouter.navigate("/help", { trigger: true });
});
</script>
<div class="jumbotron">
<h3>Backbone PushState Test</h3>
</div>
<div class="row"></div>
Now, without pushState enabled I have no issue remote linking to this route, ie http://localhost/Home/Index#test/sometext
The result of which is that the div with a class of .row is now "Hello, sometext".
The problem
Enabling pushState will allow us to replace that pesky # in the URL with a /, ie: http://localhost/Home/Index/test/sometext. We can use the Backbone method of router.navigate("url", true); (as well as other methods) to use adjust the URL manually. However, this does not solve the problem of remote linking. So, when trying to access http://localhost/Home/Index/test/sample you just end up with the typical 404.0 error served by IIS. so, I assume that it is handled in in the RouteConfig.cs file - inside, I add a "CatchAll" route:
routes.MapRoute(
name: "CatchAll",
url: "{*clientRoute}",
defaults: new { controller = "Home", action = "Index" }
);
I also uncomment out the pushState and root attributes in the Backbone.history.start(); method:
Backbone.history.start({
pushState: true,
root: "/Home/Index/"
});
var Route = Backbone.Router.extend({
routes: {
"test/:id": function (event) {
$(".row").html("Hello, " + event);
},
"help": function () {
alert("help!");
}
}
});
var appRouter = new Route();
//appRouter.navigate("/test/sometext", { trigger: true });
//appRouter.navigate("/help", { trigger: true });
This allows me to at least let get past the 404.0 page when linking to these routes - which is good. However, none of the routes actually "trigger" when I head to them. After attempting to debug them in Chrome, Firefox, and IE11 I notice that none of the events fire. However, if I manually navigate to them using appRouter.navigate("/help", { trigger: true }); the routes are caught and events fired.
I'm at a loss at this point as to where I should start troubleshooting next. I've placed my Javascript inside of the $(document).ready() event as well as the window.onload event also (as well as not inside of an event); none of these correct the issue. Can anyone offer advice on where to look next?
You simply have to move Backbone.history.start after the "new Route" line.
var Route = Backbone.Router.extend({
routes: {
"test/:id": function (event) {
$(".row").html("Hello, " + event);
},
"help": function () {
alert("help!");
}
}
});
var appRouter = new Route();
Backbone.history.start({
pushState: true,
root: "/Home/Index/"
});
Make sure you go to ".../Home/Index/help". If it doesn't work, try temporarily removing the root and go to ".../help" to see if the root is the problem.
If you still have troubles, set a js breakpoint in Backbone.History.loadUrl on the "return" line. It is called from the final line of History.start to execute the current browser url on page load. "this.matchRoot()" must pass then, "fragment" is matched against each "route" or regexp string in "this.handlers". You can see why or why not the browser url matches the route regexps.
To set to the js breakpoint, press F12 in the browser to open the dev console, press Ctrl-O or Ctrl-P to open a js file, then type the name of the backbone js file. Then search for "loadUrl:". You can also search for "Router =" to find the start of the router class definition (same as for "View =" and "Model =" to find the backbone view/model implementation code). I find it quite useful to look at the backbone code when I have a question like this. It is surprisingly readable and what better place to get answers?
If your js files happen to be minified/compressed, preferably turn this off. Alternately you can try the browser unminify option. In Chrome this is the "{}" button or "pretty print". Then the js code is not all on 1 line and you can set breakpoints. But the function and variable names may still be mangled.
I have solved my own problem using what feels to be "hackish", via the following. If anyone can submit a better response it would be appreciated!
My Solution:
I globally override the default Backbone.Router.intilaize method (it is empty) with the following:
$(document).ready(function (event) {
var _root = "/Home/Index/";
_.extend(Backbone.Router.prototype, {
initialize: function () {
/* check for route & navigate to it */
var pathName = window.location.pathname;
var route = pathName.split(_root)[1];
if (route != undefined && route != "") {
route = "/" + route;
this.navigate("", { trigger: false });
this.navigate(route, { trigger: true });
}
}
});
});
Near the bottom of my routing registration, if a URL has a .js extension, I'd like to handle it with a particular controller (most .js content is served statically, but some is special and needs to be served via a controller). However, the following route is being skipped, and the catch-all route is handling the request.
routes.MapRoute("ContentScript", "{script}.js",
new { controller = "Content", action = "Script" },
new[] { "NameSpace.Controllers" }
);
What is the right way to do this?
In the route directly after that one every remaining request is routed like so (and this works and catches the .js files), so the issue is not in any part but the url parameter):
routes.MapRoute("ContentScript", "{*path}",
new { controller = "Content", action = "Index" },
new[] { "NameSpace.Controllers" }
);
I also tried the following, without success:
routes.MapRoute("ContentScript", "{*script}",
new { controller = "Content", action = "Script" },
new { script = new RegexConstraint("\\.js$") },
new[] { "NameSpace.Controllers" }
);
you have to add handler to the web.config so it can handle it ...
some thing like that :
<system.webserver>
<handlers>
<add name="scripts" path="*.js" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers>
</system.webserver>
stackoverflow link #1
stackoverflow link #2
The problem was an IgnoreRoute that I was unaware of (the RouteRegistry.cs file is 1,469 lines long... I have not studied it in its entirety, yet). js files are being handled in managed code--they were just being taken out by this before my route could handle the request.
routes.IgnoreRoute("{*path}",
new { path = new RegexConstraint(#"[^?]*\.(gif|jpe?g|png|ico|js|swf|css|txt|html?|xml|pdf)") }
);
I've seen a lot of documentation about integration between ASP .NET web sites and Facebook, but I haven't found a simple working example, even using Facebook C# SDK.
All I want is a "login with Facebook" example, and to get basic user information (such as name, email and photo).
Can you guys help me please?
Thanks a lot!
as you say using Facebook C# SDK, then here is path and some code for canvas application:
1- Create your web application from visual studio
2- install nuget and get by nuget Facebook C# SDK
3- from https://developers.facebook.com/apps/ create and configure your app.
4- Your web config for facebook integration :
<configuration>
<configSections>
<section name="facebookSettings" type="Facebook.FacebookConfigurationSection" />
</configSections>
<facebookSettings appId="123..." appSecret="abc...." siteUrl="http://apps.facebook.com/myapp/" canvasPage="http://app.facebook.com/myapp" secureCanvasUrl="https://myapp.com/" canvasUrl="http://myapp.com/" cancelUrlPath="http://www.facebook.com/" />
...
By using sdk, you can parse signed request or cookie written by facebook js sdk
FacebookWebContext fbWebContext = new FacebookWebContext();
//Check if user auhtenticated
bool IsAuthenticated = fbWebContext.IsAuthenticated();
Here you can have friend count by:
FacebookWebClient fbWebClient = new FacebookWebClient();
dynamic result = fbWebClient.Get("me/friends");
var friends = result["data"];
int frienCount = friends.Count;
For the client side:
<body>
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function () {
FB.init({
appId: '123...',
status: true,
cookie: true,
xfbml: true,
oauth:true });
};
(function () {
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
} ());
<!-- rest of your html -->
</body>
For login & asking permission from javascript
FB.getLoginStatus(function(response) {
console.log( response );
if ((response.status)&&(response.status=='connected')) {
//successs
} else {
//user declined
}, {scope:'user_likes, offline_access'}
});
I prefer in my project to client side login thus not yet registered user have landing page, if for example submit form then I call code block above.
Note: you have to set P3P header for Internet explorer to read/write cookie depending of your server. for IIS, global.asax:
protected void Application_BeginRequest(Object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("p3p", "CP=\"CAO PSA OUR\"");
}
VoliĆ
I have an ASP.NET website that uses Forms authentication
<authentication mode="Forms">
<forms name="NewsCoreAuthentication" loginUrl="~/Default.aspx" defaultUrl="~/Default.aspx" protection="Validation" timeout="300" domain="someRootDomain.com" />
</authentication>
I need to identify if user is authenticated on web page after it was rendered to client.
To accomplish this I thought that I can read document.cookie and check if ".ASPXAUTH" is there.
But the problem is that even if I am signed in this value is empty.
How can I check that user is authenticated?
Why document.cookie is empty?
Thank you for answers. blowdart helped me to understand why authentication ticket is not accessible from client script.
The reason it's blank is because the cookie is protected by being marked as HttpOnly. This means it cannot be accessed via script. Turning this off is a very very bad idea, as XSS vulnerabilities in your site could expose it to cookie theft, so I'm not going to tell you how you can do it.
As others have said, the auth ticket is and SHOULD be httponly.
The best way to do this is to use ApplicationServices. The JSON authentication endpoint exposes IsLoggedIn and I have noticed your concern regarding server load. The overhead of a call to a static endpoint that simply checks the cookie for you is negligible. Really.
So, If you are using MsAjax, just enable application services and call Sys.Services.AuthenticationService.IsLoggedIn.
If you want to do this from raw javascript here is the codez ;-)
Add this segment to you config file
<system.web>
------------
</system.web>
<system.web.extensions>
<scripting>
<webServices>
<authenticationService enabled ="true" requireSSL="false"/>
</webServices>
</scripting>
</system.web.extensions>
The page....
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
function createXHR() {
// a memoizing XMLHttpRequest factory.
var xhr;
var factories = [
function() { return new XMLHttpRequest(); },
function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
function() { return new ActiveXObject("Msxml3.XMLHTTP"); },
function() { return new ActiveXObject("Microsoft.XMLHTTP"); } ];
for (var i = 0; i < factories.length; i++) {
try {
xhr = factories[i]();
// memoize the factory so we don't have to look for it again.
createXHR = factories[i];
return xhr;
} catch (e) { }
}
}
function isLoggedIn() {
var xhr = createXHR();
xhr.open("POST", "/Authentication_JSON_AppService.axd/IsLoggedIn", true);
xhr.onreadystatechange = function() {
if (this.readyState === 4) {
if (this.status != 200) {
alert(xhr.statusText);
} else {
alert("IsLoggedIn = " + xhr.responseText);
}
xhr = null;
}
};
xhr.setRequestHeader("content-type", "application/json");
xhr.send(null);
}
</script>
</head>
<body>
<input type="button" value="IsLoggedIn?" onclick="isLoggedIn()" />
</body>
</html>
Number one... this is a bad idea. There is absolutely no security in checking if a user is authorized on the client side. None.
But if you really want to do this... do the check in code behind, and push a value to the client that can be read via Javascript. Something akin to:
RegisterClientScript("isvalidated", "var isUserAuthenticated = " + UserAuthenticated);
You see the problem now? You could do the same thing in AJAX... but it has the same problem.
OK, I can see doing this as a simple convenience for the user... showing certain links if they are authorized for instance. But it is not secure in any way shape or form. Just do yourself a favor and handle this in code-behind.