I have successfully installed your project and I can protect media items via the Media section.
However, I am unable to redirect a member after he / sh is logged in. The returnurl query gets lost, and the login page justs redirects to the login page. Do you have any login code examples that can show me how to do the redirection based on the ReturnUrl?
I have found several posts on the old forum and 1 on codeplex, that explain there is a problem with the Umbraco Membership providers. The usercontrol I am using at the moment is using an asp.net login control, but never seems to be able to redirect.
Any help would be appreciated. Below I pasted the code I am using, maybe you can see an obvious mistake?
Protected media lacks some documentation... *blush*... but to answer your question, I don't think you need to wire up the event handlers for the login button. Login control is actually taking care of membership verification and should do the redirect if a ReturnUrl is appended to the url. For sake of testing, can you remove all event handling code (also page load code), just keep your login control on the page you've set as the login page and that should do the trick. If it's still not working, let me know your setup (may contact me on dirk at netaddicts dot be) and I'll try to repro this issue locally.
Thanks for the reply, and I did what you suggested, however without any success. After login I am just pointed to the login page. I managed to get everything working up to the point where I have to create the redirection to the download URL. The post you wrote about the protected media provides just enough information to get the project running, so you wont here me say anything about documentation.
Created a new class which i called “ForceRedirectModule”.
Register this class to the “IHttpModule” interface.
Make sure you implement the interface which will give you “Dispose” and “Int” methods for the class.
In the “Init” method we want to register to the “HttpApplication” “AuthenticateRequest” event handler, and for this example I’ve used “ForceRedirect_AuthenticateRequest”.
So once you’ve done that you class should look something like below:
public class ForceRedirectModule : IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
//throw new NotImplementedException();
}
public void Init(HttpApplication context)
{
// we use AuthenticateRequest so we have access to the user
context.AuthenticateRequest += new EventHandler(ForceRedirect_AuthenticateRequest);
public class ForceRedirectModule : IHttpModule { #region IHttpModule Members public void Dispose() { //throw new NotImplementedException(); }
public void Init(HttpApplication context) { // we use AuthenticateRequest so we have access to the user context.AuthenticateRequest += new EventHandler(ForceRedirect_AuthenticateRequest); } #endregion
The reason why we have to register to the “AuthenicateRequest” instead of “BeginRequest” is that by the time BeginRequest fires the system has worked out if the user is valid or not, i personally don’t like this but it’s the only way to do this at the moment without re-writing the full front end (cough cough i might have already started doing).
Next what we’ll do is setup some local variables which we will use a bit later on: private HttpApplication httpApp; private const string ForceRedirect = “forceredirect”; private const string MemberForceRedirect = “memberforceredirect”;
We want to modify out Init code to be the following: public void Init(HttpApplication context) { // we use AuthenticateRequest so we have access to the user context.AuthenticateRequest += new EventHandler(ForceRedirect_AuthenticateRequest); httpApp = context; }
What we are doing is just registring the context so we can use it later on for ease.
Next we want to create a private method called IsUrlValid which will be used to help filter out pages we don’t want to redirect on, this is crude but it work: private bool IsUrlValid(HttpContext context) { string url = context.Request.Url.AbsoluteUri;
// make sure it only uses if required if ((url.IndexOf(“.aspx”) > -1) && !context.Request.Url.AbsolutePath.StartsWith(“/umbraco/”) && !context.Request.Url.AbsolutePath.StartsWith(“/bin/”) && !context.Request.Url.AbsolutePath.StartsWith(“/umbraco_client/”) && !context.Request.Url.AbsolutePath.StartsWith(“/usercontrols/”) && !context.Request.Url.AbsolutePath.StartsWith(“/xslt/”) && !context.Request.Url.AbsolutePath.StartsWith(“/scripts/”) && !context.Request.Url.AbsolutePath.StartsWith(“/masterpages/”) && !context.Request.Url.AbsolutePath.StartsWith(“/install/”) && !context.Request.Url.AbsolutePath.StartsWith(“/umbraco_client/”) && !context.Request.Url.AbsolutePath.StartsWith(“/data/”) && !context.Request.Url.AbsolutePath.StartsWith(“/config/”) ) { return true; }
return false; }
Next we need to start adding some code to out ForceRedirect_AuthenticateRequest handler: void ForceRedirect_AuthenticateRequest(object sender, EventArgs e) { HttpContext context = httpApp.Context;
if (IsUrlValid(context)) { string[] paths = context.Request.Url.AbsolutePath.Replace(“.aspx”, “”).Split(‘/’);
// make sure we have data if (paths.Length > 0) { // build the dynamic path from the root System.Text.StringBuilder sb = new System.Text.StringBuilder();
// process the nodes for (int i = 0; i < paths.Length; i++) { if (!paths[i].Equals(string.Empty)) { // make sure we have the first instance so it works correctly if (sb.Length == 0) { sb.Append(“.”); }
Now what does this do, it’s quite simple it gets the current page and finds the node for this, it then doesn’t some checks to see if everything is fine, the bulk of the additional processing is done in the ForceRedirectCheck method. The ForceRedirectCheck method makes sure that the page firstly has the fields required, if not it does nothing, but if they are found and not empty then it starts processing the calling page to try and see if that page requires a redirect, this will continue until it finds a page which doesn’t redirect, yes it means you could put this into a circular dependency, but you know what that would be your own stupid fault. Below is the code for the ForceRedirectCheck: private string ForceRedirectCheck(System.Xml.XmlNode currentNode, int loop) { System.Xml.XmlNode forceRedirect = null; string returnData = “”;
// try member force redirect first if (httpApp.Context.User != null && httpApp.Context.User.Identity.IsAuthenticated) { forceRedirect = currentNode.SelectSingleNode(“./data [@alias = '" + MemberForceRedirect + "']“); }
public void Dispose() { //throw new NotImplementedException(); }
public void Init(HttpApplication context) { // we use AuthenticateRequest so we have access to the user context.AuthenticateRequest += new EventHandler(ForceRedirect_AuthenticateRequest); httpApp = context; }
if (IsUrlValid(context)) { string[] paths = context.Request.Url.AbsolutePath.Replace(“.aspx”, “”).Split(‘/’);
// make sure we have data if (paths.Length > 0) { // build the dynamic path from the root System.Text.StringBuilder sb = new System.Text.StringBuilder();
// process the nodes for (int i = 0; i < paths.Length; i++) { if (!paths[i].Equals(string.Empty)) { // make sure we have the first instance so it works correctly if (sb.Length == 0) { sb.Append(“.”); }
ReturnUrl not working
Hi,
I have successfully installed your project and I can protect media items via the Media section.
However, I am unable to redirect a member after he / sh is logged in. The returnurl query gets lost, and the login page justs redirects to the login page.
Do you have any login code examples that can show me how to do the redirection based on the ReturnUrl?
I have found several posts on the old forum and 1 on codeplex, that explain there is a problem with the Umbraco Membership providers.
The usercontrol I am using at the moment is using an asp.net login control, but never seems to be able to redirect.
Any help would be appreciated.
Below I pasted the code I am using, maybe you can see an obvious mistake?
thx, Len.
Hi Len,
Protected media lacks some documentation... *blush*... but to answer your question, I don't think you need to wire up the event handlers for the login button. Login control is actually taking care of membership verification and should do the redirect if a ReturnUrl is appended to the url. For sake of testing, can you remove all event handling code (also page load code), just keep your login control on the page you've set as the login page and that should do the trick. If it's still not working, let me know your setup (may contact me on dirk at netaddicts dot be) and I'll try to repro this issue locally.
Cheers,
/Dirk
Hey Dirk,
Thanks for the reply, and I did what you suggested, however without any success. After login I am just pointed to the login page.
I managed to get everything working up to the point where I have to create the redirection to the download URL. The post you wrote about the protected media provides just enough information to get the project running, so you wont here me say anything about documentation.
I am running version 4.0.3.
Thx, Len.
Ok Len, I'll do some checkings tonight to see if there's some quirck on using Protected media on the v403 version. Keeping you posted.
Cheers,
/Dirk
Hey Dirk,
I think I found the solution, here is some code that does the trick for me.
The ReturnUrl is added to a session variable, otherwise it is no longer available when a member is logged in.
So once you’ve done that you class should look something like below:
public class ForceRedirectModule : IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
//throw new NotImplementedException();
}
public void Init(HttpApplication context)
{
// we use AuthenticateRequest so we have access to the user
context.AuthenticateRequest += new EventHandler(ForceRedirect_AuthenticateRequest);
}
#endregion
void ForceRedirect_AuthenticateRequest(object sender, EventArgs e)
{
//throw new NotImplementedException();
}
}
The reason why we have to register to the “AuthenicateRequest” instead of “BeginRequest” is that by the time BeginRequest fires the system has worked out if the user is valid or not, i personally don’t like this but it’s the only way to do this at the moment without re-writing the full front end (cough cough i might have already started doing).
Next what we’ll do is setup some local variables which we will use a bit later on:
private HttpApplication httpApp;
private const string ForceRedirect = “forceredirect”;
private const string MemberForceRedirect = “memberforceredirect”;
We want to modify out Init code to be the following:
public void Init(HttpApplication context)
{
// we use AuthenticateRequest so we have access to the user
context.AuthenticateRequest += new EventHandler(ForceRedirect_AuthenticateRequest);
httpApp = context;
}
What we are doing is just registring the context so we can use it later on for ease.
Next we want to create a private method called IsUrlValid which will be used to help filter out pages we don’t want to redirect on, this is crude but it work:
private bool IsUrlValid(HttpContext context)
{
string url = context.Request.Url.AbsoluteUri;
// make sure it only uses if required
if ((url.IndexOf(“.aspx”) > -1) &&
!context.Request.Url.AbsolutePath.StartsWith(“/umbraco/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/bin/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/umbraco_client/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/usercontrols/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/xslt/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/scripts/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/masterpages/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/install/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/umbraco_client/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/data/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/config/”)
)
{
return true;
}
return false;
}
Next we need to start adding some code to out ForceRedirect_AuthenticateRequest handler:
void ForceRedirect_AuthenticateRequest(object sender, EventArgs e)
{
HttpContext context = httpApp.Context;
if (IsUrlValid(context))
{
string[] paths = context.Request.Url.AbsolutePath.Replace(“.aspx”, “”).Split(‘/’);
// make sure we have data
if (paths.Length > 0)
{
// build the dynamic path from the root
System.Text.StringBuilder sb = new System.Text.StringBuilder();
// process the nodes
for (int i = 0; i < paths.Length; i++)
{
if (!paths[i].Equals(string.Empty))
{
// make sure we have the first instance so it works correctly
if (sb.Length == 0)
{
sb.Append(“.”);
}
sb.AppendFormat(“/node[@urlName='{0}']“, paths[i]);
}
}
if (sb.Length > 0)
{
string domainName = context.Request.ServerVariables["SERVER_NAME"];
if (umbraco.cms.businesslogic.web.Domain.Exists(domainName))
{
System.Xml.XmlElement domain = umbraco.content.Instance.XmlContent.GetElementById(umbraco.cms.businesslogic.web.Domain.GetRootFromDomain(domainName).ToString());
if (domain != null)
{
//string currentId = node.Attributes.GetNamedItem(“id”).Value;
System.Xml.XmlNode currentNode = domain.SelectSingleNode(sb.ToString());
if (currentNode != null)
{
string redirectUrl = ForceRedirectCheck(currentNode, 0);
if (!redirectUrl.Equals(string.Empty))
{
httpApp.Context.Response.Redirect(redirectUrl);
}
}
}
}
}
}
}
}
Now what does this do, it’s quite simple it gets the current page and finds the node for this, it then doesn’t some checks to see if everything is fine, the bulk of the additional processing is done in the ForceRedirectCheck method.
The ForceRedirectCheck method makes sure that the page firstly has the fields required, if not it does nothing, but if they are found and not empty then it starts processing the calling page to try and see if that page requires a redirect, this will continue until it finds a page which doesn’t redirect, yes it means you could put this into a circular dependency, but you know what that would be your own stupid fault.
Below is the code for the ForceRedirectCheck:
private string ForceRedirectCheck(System.Xml.XmlNode currentNode, int loop)
{
System.Xml.XmlNode forceRedirect = null;
string returnData = “”;
// try member force redirect first
if (httpApp.Context.User != null && httpApp.Context.User.Identity.IsAuthenticated)
{
forceRedirect = currentNode.SelectSingleNode(“./data [@alias = '" + MemberForceRedirect + "']“);
}
if (forceRedirect == null || forceRedirect.ChildNodes.Count <= 0)
{
forceRedirect = currentNode.SelectSingleNode(“./data [@alias = '" + ForceRedirect + "']“);
}
if (forceRedirect != null && forceRedirect.ChildNodes.Count > 0)
{
int redirectId = 0;
if (int.TryParse(forceRedirect.ChildNodes[0].Value, out redirectId))
{
returnData = ForceRedirectCheck(umbraco.content.Instance.XmlContent.GetElementById(redirectId.ToString()), loop + 1);
}
}
if (returnData.Equals(string.Empty) && loop > 0)
{
returnData = umbraco.library.NiceUrl(Convert.ToInt32(currentNode.Attributes["id"].Value));
}
return returnData;
}
That’s all the code, so here is what you should have:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace TestProject
{
public class ForceRedirectModule : IHttpModule
{
private HttpApplication httpApp;
private const string ForceRedirect = “forceredirect”;
private const string MemberForceRedirect = “memberforceredirect”;
#region IHttpModule Members
public void Dispose()
{
//throw new NotImplementedException();
}
public void Init(HttpApplication context)
{
// we use AuthenticateRequest so we have access to the user
context.AuthenticateRequest += new EventHandler(ForceRedirect_AuthenticateRequest);
httpApp = context;
}
#region IsUrlValid
private bool IsUrlValid(HttpContext context)
{
string url = context.Request.Url.AbsoluteUri;
// make sure it only uses if required
if ((url.IndexOf(“.aspx”) > -1) &&
!context.Request.Url.AbsolutePath.StartsWith(“/umbraco/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/bin/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/umbraco_client/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/usercontrols/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/xslt/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/scripts/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/masterpages/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/install/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/umbraco_client/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/data/”) &&
!context.Request.Url.AbsolutePath.StartsWith(“/config/”)
)
{
return true;
}
return false;
}
#endregion
void ForceRedirect_AuthenticateRequest(object sender, EventArgs e)
{
HttpContext context = httpApp.Context;
if (IsUrlValid(context))
{
string[] paths = context.Request.Url.AbsolutePath.Replace(“.aspx”, “”).Split(‘/’);
// make sure we have data
if (paths.Length > 0)
{
// build the dynamic path from the root
System.Text.StringBuilder sb = new System.Text.StringBuilder();
// process the nodes
for (int i = 0; i < paths.Length; i++)
{
if (!paths[i].Equals(string.Empty))
{
// make sure we have the first instance so it works correctly
if (sb.Length == 0)
{
sb.Append(“.”);
}
sb.AppendFormat(“/node[@urlName='{0}']“, paths[i]);
}
}
if (sb.Length > 0)
{
string domainName = context.Request.ServerVariables["SERVER_NAME"];
if (umbraco.cms.businesslogic.web.Domain.Exists(domainName))
{
System.Xml.XmlElement domain = umbraco.content.Instance.XmlContent.GetElementById(umbraco.cms.businesslogic.web.Domain.GetRootFromDomain(domainName).ToString());
if (domain != null)
{
//string currentId = node.Attributes.GetNamedItem(“id”).Value;
System.Xml.XmlNode currentNode = domain.SelectSingleNode(sb.ToString());
if (currentNode != null)
{
string redirectUrl = ForceRedirectCheck(currentNode, 0);
if (!redirectUrl.Equals(string.Empty))
{
httpApp.Context.Response.Redirect(redirectUrl);
}
}
}
}
}
}
}
}
#endregion
#region ForceRedirectCheck
private string ForceRedirectCheck(System.Xml.XmlNode currentNode, int loop)
{
System.Xml.XmlNode forceRedirect = null;
string returnData = “”;
// try member force redirect first
if (httpApp.Context.User != null && httpApp.Context.User.Identity.IsAuthenticated)
{
forceRedirect = currentNode.SelectSingleNode(“./data [@alias = '" + MemberForceRedirect + "']“);
}
if (forceRedirect == null || forceRedirect.ChildNodes.Count <= 0)
{
forceRedirect = currentNode.SelectSingleNode(“./data [@alias = '" + ForceRedirect + "']“);
}
if (forceRedirect != null && forceRedirect.ChildNodes.Count > 0)
{
int redirectId = 0;
if (int.TryParse(forceRedirect.ChildNodes[0].Value, out redirectId))
{
returnData = ForceRedirectCheck(umbraco.content.Instance.XmlContent.GetElementById(redirectId.ToString()), loop + 1);
}
}
if (returnData.Equals(string.Empty) && loop > 0)
{
returnData = umbraco.library.NiceUrl(Convert.ToInt32(currentNode.Attributes["id"].Value));
}
return returnData;
}
#endregion
}
}
is working on a reply...