ASP.NET Session Problem in ASHX and using Google Chrome and Firefox - asp.net

Am not sure why when using IE, retrieving session values works just fine, but when using Google Chrome and Firefox, it's not returning any?
I have already included IRequiresSessionState/IReadOnlySessionState in generic handler class, but still did not work.
So my last resort was to add my session values as a query string in generic handler.
But I still want to know why and what's wrong in Chrome and Firefox? Thanks.
UPDATE:
here's the way I handle my Seesion SessionManager
It works perfectly in ASPX pages and in IE, Chrome, and Firefox
but when used in my ASHX page. sample code below
<%# WebHandler Language="C#" Class="Upload" %>
using System;
using System.Web;
using System.Web.SessionState;
using System.IO;
public class Upload : IHttpHandler, IReadOnlySessionState
{
SessionManager sm;
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
context.Response.Expires = -1;
sm = new SessionManager();
try
{
HttpPostedFile postedFile = context.Request.Files["Filedata"];
string uploadedas = string.Empty;
if (context.Request.QueryString["as"] != null)
{
uploadedas = context.Request.QueryString["as"];
}
string username = sm.Username;
string sessionid = sm.SessionID;
//
// MORE CODES HERE
//
context.Response.Write(response);
context.Response.StatusCode = 200;
}
catch (Exception ex)
{
context.Response.Write("Error: " + ex.Message + "\r\n\r\n" + ex.StackTrace);
}
}
public bool IsReusable {
get {
return false;
}
}
}
sm.Username and sm.SessionID returns an emptry string when Chrome and Firefox is used.. but as I said earlier, those are working perfectly in ASPX pages even in different browsers.

A session is a type of cookie. Make sure you have cookies enabled on all the browsers you are testing in.

How are you calling your ashx from your page? Can you give sample code?
Do you use Flash to call the ashx? Flash has a cookie bug that always sends IE cookies to the server whichregardless of which browser you are using which makes accessing ASP.NET Session hard since it relies on a cookie.

Related

Is there a version of IsLocalUrl for WebForms?

I'm writing a mixed app using some MVC and some Webforms screens. I need to invoke a WebForms screen with a ReturnUrl in a hidden field. I'd like to validate the ReturnUrl before transferring back to it. MVC has an Url.IsLocalUrl function, but it doesn't seem to work on WebForm screens, so I use the UrlHelper class. But when I use it I get a NullReferenceException:
UrlHelper url = new UrlHelper();
if (url(validaddr)) <--- get NullReferenceException
{
}
Any ideas?
I use the below extension method to validate local url's in web forms. Hope this helps you too.
public static bool IsLocalURL(this string _url)
{
bool flag = false;
try
{
var url = new Uri(_url);
var ctx = HttpContext.Current;
if (url.Host.Equals(ctx.Request.Url.Host) && url.Port.Equals(ctx.Request.Url.Port))
flag = true;
}
catch { }
return flag;
}
This extension method is for string. You may create a similar for Uri class as well.
I came here trying to solve the same problem. I used RequestExtensions.IsUrlLocalToHost in System.Web.WebPages (available in nuget package Microsoft.AspNet.WebPages v3.2.6)
Doc here: https://learn.microsoft.com/en-us/dotnet/api/system.web.webpages.requestextensions.isurllocaltohost?view=aspnet-webpages-3.2
Assuming you have an HttpRequest to work with (you will probably need this anyway to compare the URL to the underlying host URL), you need to first convert your HttpRequest to HttpRequestBase:
var httpRequestBase = new HttpRequestWrapper(HttpContext.Current.Request) as HttpRequestBase;
Then you can perform:
httpRequestBase.IsUrlLocalToHost(myUrlString)
Code should be:
UrlHelper url = new UrlHelper();
if (url.IsLocalUrl(validaddr)) <--- get NullReferenceException
{
}

.Net Server-Sent Events using HttpHandler not working

I have been trying to implement an event driven push to a client browser. I am using ReactiveX to produce the async task from the events but I can't even get my HttpHandlers to output their response.
I have tried with a simple HttpHandler:
public class Handler2 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/event-stream";
HttpResponse response = context.Response;
DateTime startdate = DateTime.Now;
while (startdate.AddMinutes(10) > DateTime.Now)
{
JavaScriptSerializer js = new JavaScriptSerializer();
string responseText = DateTime.Now.TimeOfDay.ToString();
response.Write(string.Format("data: {0}",js.Serialize(responseText)));
response.Flush();
System.Threading.Thread.Sleep(1000);
}
response.Close();
}
public bool IsReusable
{
get
{
return false;
}
}
}
with the following client side code:
function initialize() {
if (window.EventSource == undefined) {
document.getElementById('targetDiv').innerHTML = "Your browser doesn't support Server Side Events.";
return;
}
var source = new EventSource('Handler2.ashx');
source.onopen = function (event) {
document.getElementById('targetDiv').innerHTML += 'Connection Opened.<br>';
};
source.onerror = function (event) {
if (event.eventPhase == EventSource.CLOSED) {
document.getElementById('targetDiv').innerHTML += 'Connection Closed.<br>';
}
};
source.onmessage = function (event) {
document.getElementById('targetDiv').innerHTML += event.data + '<br>';
};
}
I have more a more complex HttpTaskAsyncHandler ready to hook up, but I can't even get this working >_<
I get the Connection Opened message, Handler2.ashx appears to remain connected (Looking at Chrome dev tools / Network).
I am, on the other hand, getting some data from a SignalR connection?
"ws://localhost:50022/ed4b66c7eb394a8789b5f6a631f4ff09/arterySignalR/connect?.."
Have I set it up wrong?
As far as I've seen on other examples, this code should be working as-is. Please could anyone help me. I just want a simple SSE control that I can trigger from server side events.
Thanks in advance
I had given this answer before, but let me elaborate:
Looking at the Network tab in Google Chrome developer tools reveals quite a lot from your http://live.meetscoresonline.com/test-sse.aspx
There are no SSE being generated at all - to see this click on the Others button under Network, this is where you would normally be able to track the SSE data stream
I use the following code in my SSE's with a simple HTTPListener and it works well without the delays you mentioned, and always shows up correctly across browsers when using this polyfill
res.AddHeader("Content-Type", "text/event-stream")
res.AddHeader("Cache-Control", "no-cache")
res.AddHeader("Access-Control-Allow-Origin", "*")
res.KeepAlive = True

ASP.NET Forms Authentication Cookie not set in Safari

I have a ASP.NET Web Service which exposes a method called DoLogin
[WebService(Namespace = "http://rtns.ism.ec/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
[ScriptService]
public class UserManagerService : WebServiceBase
{
[WebMethod(EnableSession=true)]
[ScriptMethod]
public ResponseBase<bool> DoLogin(LoginCredentials Credentials)
{
Credentials.IpAddress = HttpContext.Current.Request.UserHostAddress;
Credentials.ServerID = Environment.MachineName;
Credentials.SystemID = WebConfigurationManager.AppSettings["SYSTEM_ID"];
Credentials.UserAgent = HttpContext.Current.Request.UserAgent;
try
{
DataResponse<User> resp = UserManager.LoginUser(Credentials);
if (resp.Code)
{
FormsAuthentication.SetAuthCookie(Credentials.Email, true);
HttpContext.Current.Session.Add(Constants.Identifiers.USER_SESSION_INFO_IDENTIFIER, resp.Data);
}
return resp;
}
catch (Exception _ex)
{
ISM.Essentials.Business.LogManager.SaveLog(_ex);
return new ResponseBase<bool> { Message = MessageManager.Instance[Constants.Messages.E_GENERIC_FAILURE, Credentials.CultureID] };
}
}
}
I have a JQuery client, which makes the call:
function loginSubmitHandler() {
var objeto = {
Email: $('#txtUser').val(),
Password: $('#txtPassword').val(),
CultureID: $('#hddCulture').val()
};
utils.startAjaxCall('../Services/UserManagerService.asmx/DoLogin', { Credentials: objeto }, function(data) {
if (data.d.Code) {
window.location.replace('home.aspx');
}
else
{
utils.alert(locals.Information, locals.Accept, data.d.Message);
}
});
return false;
}
When I log in with icorrect credentials, the alert with the message sent from the server appears. If I give correct credentials, the page is redirected to home.aspx
This code is working 100% fine since the begining in the following browsers:
IE6, 7, 8, 9
Mozilla
IE9 Windows Phone
Android 2.3 Browser
Safari 5.1 for Windows
I've just got a Mac (first ever) and when I tried to access my website, I noticed an extrange behavior. I give correct login credentials, I'm redirected to home, but the FormsAuthentication mechanism redirects back to the login page.
It seems like the Auth cookie returned back from the server is just ignored.
This is not an issue with cross domain cookies, as I'm calling the web server in the same web application/domain.
Any ideas on how to make Safari for Mac to accept the cookies returned in an Ajax Web Service call?
The problem might be that safari will not set cookies with non-ASCII characters. Try using encodeURIComponent() function on cookie values. Here is a link with similar problem:
Strange problem with cookies in Safari and Asp.net

How do I get ASP.NET WebForms Routing to route .asmx JSON calls properly?

I am attempting to implement multi-tenancy in a legacy ASP.NET WebForms app. I want the URL to indicate the proper client, like so:
http://example.com/client_name/Default.aspx
http://example.com/client_name/MyWebService.asmx
However, I cannot get it to route the .asmx's properly. This routing rule picks up all incoming urls just fine:
routes.Add("ClientSelector", new System.Web.Routing.Route
(
"{client}/{*path}",
routeHandler: new ClientRoute()
));
But I am having issues with handling .asmx calls. Here's my IRouteHandler, below. The error I get is:
A first chance exception of type 'System.Web.Services.Protocols.SoapException' occurred in System.Web.Services.dll
Additional information: Unable to handle request without a valid action parameter. Please supply a valid soap action.
It's supposed to be JSON, but for some reason it's not working. I am setting the content-type - if I send this same exact request without routing, it works fine.
public class ClientRoute : System.Web.Routing.IRouteHandler
{
private string m_Path;
private string m_Client;
public ClientRoute() { }
public bool IsReusable { get { return true; } }
public IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
{
this.m_Path = (string)requestContext.RouteData.Values["path"];
this.m_Client = (string)requestContext.RouteData.Values["client"];
string virtualPath = "~/" + this.m_Path;
bool shouldValidate = false;
if (shouldValidate && !UrlAuthorizationModule.CheckUrlAccessForPrincipal(
virtualPath, requestContext.HttpContext.User,
requestContext.HttpContext.Request.HttpMethod))
{
requestContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
requestContext.HttpContext.Response.End();
return null;
}
else
{
HttpContext.Current.RewritePath(virtualPath);
HttpContext.Current.Items.Add("Client", this.m_Client);
if (virtualPath.EndsWith(".aspx"))
return (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page));
else
{
var asmxPos = virtualPath.IndexOf(".asmx", StringComparison.OrdinalIgnoreCase);
if (asmxPos >= 0)
{
// What goes here? This isn't working...
var asmxOnlyVirtualPath = virtualPath.Substring(0, asmxPos + 5);
return new System.Web.Services.Protocols.WebServiceHandlerFactory().GetHandler(
HttpContext.Current, HttpContext.Current.Request.HttpMethod, asmxOnlyVirtualPath, HttpContext.Current.Server.MapPath(asmxOnlyVirtualPath));
}
else
return new StaticRoute();
}
}
}
}
Relevant links:
Getting ScriptHandlerFactory handler
The open source http://www.teamlab.com project is built with ASP.NET Webforms, and uses a multitenant/saas model. I noticed you posted another question inquiring about multitenancy.
Perhaps you can look into their code for reference ideas.
I tried my best, ended up failing, and converted all my web services to WCF .svc services instead.

Using ASP.NET AJAX UpdatePanel with Handlers

Im using UpdatePanel for some controls specially for captchas so, when a AsyncPostBack is performed triggered by a button "btnQuery", How can I tell to the .ashx (Handler for Captcha) to refresh it self?
Im using session to validate the Image on Captcha to the Num on the input below the image
this is the Handler :
<%# WebHandler Language="C#" Class="captcha" %>
using System;
using System.Web;
using System.Web.SessionState;
using System.Drawing;
public class captcha : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/GIF";
Bitmap imagen_GIF = new System.Drawing.Bitmap(80, 30);
Graphics grafico = System.Drawing.Graphics.FromImage(imagen_GIF);
grafico.Clear(Color.Gainsboro);
Font tipo_fuente = new Font("Comic Sans", 12, FontStyle.Bold);
string randomNum = string.Empty;
Random autoRand = new Random();
for (int x = 0; x < 5; x++)
{
randomNum += System.Convert.ToInt32(autoRand.Next(0, 9)).ToString();
}
int i_letra = System.Convert.ToInt32(autoRand.Next(65, 90));
string letra = ((char)i_letra).ToString();
randomNum += letra;
context.Session["RandomNumero"] = randomNum;
grafico.DrawString(randomNum, tipo_fuente, Brushes.Black, 5, 5);
imagen_GIF.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif);
tipo_fuente.Dispose();
grafico.Dispose();
imagen_GIF.Dispose();
}
public bool IsReusable { get { return false; } }
}
I want to refresh the image.. not just doing this :
public void postbackear()
{
string script = string.Format("Sys.WebForms.PageRequestManager.getInstance()._doPostBack('{0}', '');",
btnConsulta.ID);
ScriptManager.RegisterStartupScript(this.Page, typeof(string), "Refresh", script, true);
}
Try caching options for handlers such as
context.Response.Cache.SetExpires(DateTime.Now);
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetValidUntilExpires(false);
If above not works only idea I got left is calling handler with queryString so that image source is not same any time you call
Image1.ImageUrl = "Handler.aspx?guid=" + Guid.NewGuid();
Is the image inside the UpdatePanel? I'd put it there if it isn't. Also, each time the panel updates, make sure the url for the image unique so that clients (browsers) or proxies won't use a cached image. A Guid tacked on as a querystring parameter should do the trick (e.g. YourImageHandler.ashx?xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
Angel,
The image is not being requested again from the server, so there is no opportunity for the handler to execute. To get that to execute again, you must make the browser retrieve the image again.
That said, in your async postback, if nothing about the image is updated, the browser will have no reason to fetch it again regardless of cache settings, etc.
You could solve this with script, but an easier way is to take Myra's advice and append a GUID to the query string of the image and change that GUID as part of your async postback. This will update URL of the image needed on the client and force it to go back to the server to get the new image.
If this does not solve the problem, please post the section of your web.config that maps requests to the image handler as well as the code you use to add the image to the page.

Resources