Monday, April 25, 2005

HttpModule to solve glitches when using a posting as login form

Via Stefan :

HttpModule to solve glitches when using a posting as login form

When I used this module I got in to a problem.

Recreation of the issue:

1. Create a posting as admin
2. Submit it for approval
3. Go to Approval Assistant and approve it from there

Even though it approves the posting it throws this exception:

A posting created and approved with the name 'TestApproveViaAssitant' Approve operation of the selected pages was unsuccessful.
Microsoft.ContentManagement. Publishing.CmsInvalidObjectStateException: Invalid version for current Posting. The object referred to by this Web request has already been retrieved by another mechanism, for example Searches.GetByGUID. The version of the object requested by this Web request is not consistent with the previously retrieved version. ---> System.Runtime. InteropServices.COMException (0x80041B5B): Invalid version for current Posting. The object referred to by this Web request has already been retrieved by another mechanism, for example Searches.GetByGUID. The version of the object requested by this Web request is not consistent with the previously retrieved version. atMicrosoft.ContentManagement. Interop.Publishing. CmsHttpContextClass. get_Posting() at Microsoft. ContentManagement. Publishing. CmsAspContext. get_Posting() --- End of inner exception stack trace --- at Microsoft. ContentManagement. Publishing. CmsAspContext. get_Posting() at Microsoft. ContentManagement. WebAuthor. ApprovalAssistant. OnPostingApproveDecline(Object sender, EventArgs e)


I was never heard of this issue with approval assistant before. So I was digging bit in on CmsAuthorizationModule and came up with a bit different EnhancedCmsAuthorizationModule which worked without any problem.

Modified code :

using System;
using System.Web;using System.Configuration;
using Microsoft.ContentManagement.Publishing;
using Microsoft.ContentManagement.Web.Security;
namespace StefanG.HttpModule
{

public class EnhancedCmsAuthorizationModule: IHttpModule
{
public virtual void Init(HttpApplication application)
{
if (application == null)
{
throw new ArgumentNullException("HttpApplication == null");
}
// register new Authorization handler
application.AuthorizeRequest += new EventHandler(this.OnAuthorizeRequest);
}

public virtual void Dispose()
{
// nothing to do
}

private void OnAuthorizeRequest(object source, EventArgs e)
{
HttpApplication httpApplication = (HttpApplication)source;
try
{
// lets try to retrieve the current CmsHttpContext
CmsHttpContext cmsContext = CmsHttpContext.Current;
// ok, we got the context. Now lets see if we have permission
// to access the current item.
// If not, lets present the login page to the user
if (!cmsContext.UserHasRightToBrowse())
{
redirectToLoginPage(httpApplication);
}
if (!cmsContext.ChannelItemIsVisible())
{
cmsContext.Dispose();

}
catch (CmsAccessDeniedException)
{
// ok, no luck accessing the context. Access denied.
// We need to logout and redirect to login page
redirectToLoginPage(httpApplication);
}
}

private void redirectToLoginPage(HttpApplication application)
{
// throw away old authentication token to allow access
// to logon posting as guest user
CmsFormsAuthentication.SignOut();
// get the URL to the login posting from the appSettings section of
// the Web.Config
string loginUrl = ConfigurationSettings.AppSettings["LoginUrl"];
// we need to call the login page with the ReturnURL to the item we
// tried to access if possible we will use the friendly URL
string ReturnURL = HttpUtility. UrlEncode (application. Context. Request. QueryString ["NRORIGINALURL"]);
if (ReturnURL == null)
ReturnURL = HttpUtility. UrlEncode (application. Context. Request. Url. AbsolutePath + application. Context. Request. Url. Query);
// ok, now lets redirect to the login page
application. Context. Response. Redirect (loginUrl+"?ReturnUrl="+ ReturnURL);
application. CompleteRequest();
}
}
}

N.B : If the posting is approved with the different instance, the issue was not there!

2 Comments:

Anonymous Stefan Goßner [MSFT] said...

Hi Chester,

good catch but a better solution is the following:

if (!cmsContext.ChannelItemIsVisible())
{
cmsContext.Dispose();
}

Cheers,
Stefan

5:38 PM  
Blogger Chester said...

Hi Stefan,

Thanks for pointing out. I was doing it in the wrong way!

Cheers,
Chester

5:58 PM  

Post a Comment

<< Home