We are currently adding Flash to a site. There are about 20-30 values that are coming from a combination of Umbraco Nodes + Membership information from a 3rd party. So far the membership information is being stored in an object in Session. The site works perfect when I log in and just use the site regularly.
My hope was to be able to have Flash call a /base method which would return an XML feed. This also works when I hard code in the Membership object. Now when I try to grab users information session, I keep getting a Null Exception.
I could have sworn this worked, but I could be wrong. Can you do this? Can you grab a session object from a REST call?
It's possible that you can't access Session because of the way the type is instantiated (it's done with Reflection), although I'd expect that HttpContext.Current.Session should work, as that's just a static property which resides in the request life cycle.
Thanks. I checked out the articles and apparently, you can't do this without adding a Handler. Apparently, it will be fixed in 4.6, but that doesn't help me now. I've looked at the code in 4.6, and tried to create a .dll to create a handler similar to what was done in the article above, but that failed.
namespace BaseExtension
{
using System;
using System.IO;
using System.Reflection;
using System.Web;
using System.Web.SessionState;
using System.Xml;
using umbraco.presentation.umbracobase;
public class requestModule : IHttpModule
{
private HttpApplication mApp;
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication httpApp)
{
// httpApp.PostAuthorizeRequest += new EventHandler(httpApp_PreRequestHandlerExecute);
httpApp.PostAcquireRequestState += new EventHandler(httpApp_PostAcquireRequestState);
httpApp.PostMapRequestHandler += new EventHandler(httpApp_PostMapRequestHandler);
}
void httpApp_PostMapRequestHandler(object sender, EventArgs e)
{
//remove extension and split the url
HttpApplication httpApp = (HttpApplication)sender;
string url = httpApp.Context.Request.RawUrl;
if (url.ToLower().StartsWith("/base/"))
{
if (httpApp.Context.Handler is IReadOnlySessionState || httpApp.Context.Handler is IRequiresSessionState)
{
// no need to replace the current handler
return;
}
// swap the current handler
httpApp.Context.Handler = new MyHttpHandler(httpApp.Context.Handler);
}
}
void httpApp_PostAcquireRequestState(object sender, EventArgs e)
{
HttpApplication httpApp = (HttpApplication)sender;
//remove extension and split the url
string url = httpApp.Context.Request.RawUrl;
if (url.ToLower().StartsWith("/base/"))
{
MyHttpHandler resourceHttpHandler = HttpContext.Current.Handler as MyHttpHandler;
if (resourceHttpHandler != null)
{
// set the original handler back
HttpContext.Current.Handler = resourceHttpHandler.OriginalHandler;
}
if (url.ToLower().Contains(".aspx"))
url = url.Substring(0, url.IndexOf(".aspx"));
object[] urlArray = url.Split('/');
//There has to be minimum 4 parts in the url for this to work... /base/library/method/[parameter].aspx
if (urlArray.Length >= 4)
{
string extensionAlias = urlArray[2].ToString();
string methodName = urlArray[3].ToString();
httpApp.Response.ContentType = "text/xml";
restExtension myExtension = new restExtension(extensionAlias, methodName);
if (myExtension.isAllowed)
{
string respone = invokeMethod(myExtension, urlArray);
if (respone.Substring(0, 7) == "<error>")
{
httpApp.Response.StatusCode = 500;
httpApp.Response.StatusDescription = "Internal Server Error";
}
httpApp.Response.Output.Write(respone);
}
else
{
httpApp.Response.StatusCode = 500;
httpApp.Response.StatusDescription = "Internal Server Error";
//Very static error msg...
httpApp.Response.Output.Write("<error>Extension not found or permission denied</error>");
}
//end the resposne
httpApp.Response.End();
}
}
}
private string invokeMethod(restExtension myExtension, object[] paras)
{
try
{
//So method is either not found or not valid... this should probably be moved...
if (!myExtension.method.IsPublic || !myExtension.method.IsStatic)
return "<error>Method has to be public and static</error>";
else //And if it is lets continue trying to invoke it...
{
//lets check if we have parameters enough in the url..
if (myExtension.method.GetParameters().Length > (paras.Length - 4)) //Too few
return "<error>Not Enough parameters in url</error>";
else
{
//We have enough parameters... lets invoke..
//Create an instance of the type we need to invoke the method from.
Object obj = Activator.CreateInstance(myExtension.type);
Object response;
//umbracoBase.baseBinder bBinder = new baseBinder();
if (myExtension.method.GetParameters().Length == 0)
{
//response = myMethod.method.Invoke(obj, BindingFlags.Public | BindingFlags.Instance, bBinder, null, System.Globalization.CultureInfo.CurrentCulture);
response = myExtension.method.Invoke(obj, null); //Invoke with null as parameters as there are none
}
else
{
//We only need the parts of the url above the number 4 so we'll
//recast those to objects and add them to the object[]
//Getting the right lenght.. 4 is the magic number dum di dum..
object[] methodParams = new object[(paras.Length - 4)];
int i = 0;
foreach (ParameterInfo pInfo in myExtension.method.GetParameters())
{
Type myType = Type.GetType(pInfo.ParameterType.ToString());
methodParams[(i)] = Convert.ChangeType(paras[i + 4], myType);
i++;
}
//Invoke with methodParams
//response = myMethod.method.Invoke(obj, BindingFlags.Public | BindingFlags.Instance, bBinder, methodParams, System.Globalization.CultureInfo.CurrentCulture);
response = myExtension.method.Invoke(obj, methodParams);
}
/*TODO - SOMETHING ALITTLE BETTER THEN ONLY CHECK FOR XPATHNODEITERATOR OR ELSE do ToString() */
if (response != null)
{
switch (myExtension.method.ReturnType.ToString())
{
case "System.Xml.XPath.XPathNodeIterator":
return ((System.Xml.XPath.XPathNodeIterator)response).Current.OuterXml;
case "System.Xml.Linq.XDocument":
return response.ToString();
case "System.Xml.XmlDocument":
XmlDocument xmlDoc = (XmlDocument)response;
StringWriter sw = new StringWriter();
XmlTextWriter xw = new XmlTextWriter(sw);
xmlDoc.WriteTo(xw);
return sw.ToString();
default:
string strResponse = ((string)response.ToString());
if (myExtension.returnXML)
{
//do a quick "is this html?" check... if it is add CDATA...
if (strResponse.Contains("<") || strResponse.Contains(">"))
strResponse = "<![CDATA[" + strResponse + "]]>";
return "<value>" + strResponse + "</value>";
}
else
{
HttpContext.Current.Response.ContentType = "text/html";
return strResponse;
}
}
}
else
{
if (myExtension.returnXML)
return "<error>Null value returned</error>";
else
return string.Empty;
}
}
}
}
catch (Exception ex)
{
//Overall exception handling...
return "<error><![CDATA[MESSAGE:\n" + ex.Message + "\n\nSTACKTRACE:\n" + ex.StackTrace + "\n\nINNEREXCEPTION:\n" + ex.InnerException + "]]></error>";
}
}
}
// a temp handler used to force the SessionStateModule to load session state
public class MyHttpHandler : IHttpHandler, IRequiresSessionState
{
internal readonly IHttpHandler OriginalHandler;
public MyHttpHandler(IHttpHandler originalHandler)
{
OriginalHandler = originalHandler;
}
public void ProcessRequest(HttpContext context)
{
// do not worry, ProcessRequest() will not be called, but let's be safe
throw new InvalidOperationException("MyHttpHandler cannot process requests.");
}
public bool IsReusable
{
// IsReusable must be set to false since class has a member!
get { return false; }
}
}
}
#endregion
Problem is, I don't quite know how to add this to my web.config to get this to call instead of the regular handler (which is what keeps happening). In the example given, it basically just had me remove the ,umbraco from the:
Sorry, I mentioned that I had to use other code. This is the code for Umbraco 4.6 and I couldn't get it to work in 4.5.2. (I didn't try that hard though).
Using /base with session variables
We are currently adding Flash to a site. There are about 20-30 values that are coming from a combination of Umbraco Nodes + Membership information from a 3rd party. So far the membership information is being stored in an object in Session. The site works perfect when I log in and just use the site regularly.
My hope was to be able to have Flash call a /base method which would return an XML feed. This also works when I hard code in the Membership object. Now when I try to grab users information session, I keep getting a Null Exception.
I could have sworn this worked, but I could be wrong. Can you do this? Can you grab a session object from a REST call?
If not, does anyone have any advice to do this?
Thanks,
C
How are you accessing Session? I've seen some posts on this topic before but I haven't worked with /base so I've never looked into it, here's a few that I found though: http://our.umbraco.org/forum/developers/api-questions/13819-Session-acces-in-base-methods?p=0 http://our.umbraco.org/forum/core/general/5154-HttpContextCurrentSession-when-using-rest-extensions?p=0
It's possible that you can't access Session because of the way the type is instantiated (it's done with Reflection), although I'd expect that HttpContext.Current.Session should work, as that's just a static property which resides in the request life cycle.
Thanks. I checked out the articles and apparently, you can't do this without adding a Handler. Apparently, it will be fixed in 4.6, but that doesn't help me now. I've looked at the code in 4.6, and tried to create a .dll to create a handler similar to what was done in the article above, but that failed.
Problem is, I don't quite know how to add this to my web.config to get this to call instead of the regular handler (which is what keeps happening). In the example given, it basically just had me remove the ,umbraco from the:
Would that be just like this: type="BaseExtensions.requestModule"
Yes. I had to use some other code, but that was my exact problem.
-C
So did you get it to work?
I think you might also be able to add multiple types, like the code below (but i didnt trie it)
I tried compiling your code, but it didnt work with me either. (though I didnt trie this here below)
Yes. Got it to work. The problem was that I needed to replace the umbraco.presentation.umbracobase.requestModule with the entirely new module.
-C
Really? I tried that, but it didnt work for me.
So the code you wrote is a precise replacement for the original handler?
Did you change anything before you got it to work? Otherwise you could mark this thread as solved.
I might trie it again, but last time it didnt work.
Sorry, I mentioned that I had to use other code. This is the code for Umbraco 4.6 and I couldn't get it to work in 4.5.2. (I didn't try that hard though).
I used this code: http://our.umbraco.org/forum/developers/api-questions/7973-MemberGetCurrentMember()-in-base
I believe this thread has also been marked as solved.
is working on a reply...