Showing posts with label CSRRenderMode. Show all posts
Showing posts with label CSRRenderMode. Show all posts

Thursday, March 21, 2013

Setting Custom ListFormWebPart Parameters in List Definition

In order to set custom ListFormWebPart parameters when defining list definition schema, you need to modify Form tag in schema.xml. Please refer to the following sample, used to add CSRRenderMode property to ListFormWebPart and set it to ServerRender:

<Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" UseDefaultListFormWebPart="False">
    <WebParts>
      <AllUsersWebPart WebPartZoneID="Main" WebPartOrder="1">
        <![CDATA[
<WebPart xmlns="http://schemas.microsoft.com/WebPart/v2">
  <Assembly>Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, 
         PublicKeyToken=71e9bce111e9429c</Assembly>                         
  <TypeName>Microsoft.SharePoint.WebPartPages.ListFormWebPart</TypeName>
  <PageType>PAGE_NEWFORM</PageType>
  <CSRRenderMode xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">ServerRender</CSRRenderMode>

</WebPart>]]>
      </AllUsersWebPart>
    </WebParts>
</Form>

You can change Microsoft.SharePoint assembly reference to 14.0.0.0 or 12.0.0.0 to use it with SharePoint 2010 or SharePoint 2007 respectfully.

SharePoint 2013 Event Receiver Redirect

It used to be a standard practice to use redirect in event receivers in SharePoint 2010 and SharePoint 2007. SharePoint 2013 has some changes in this functionality.

Redirect Option Availability

No redirect options available for ItemAdded, ItemUpdated and ItemDeleted.

Some redirect options available for ItemAdding, ItemUpdating and ItemDeleting. They are only available when the form, which initiates an event, is being rendered in CSRRenderMode.ServerRender mode. Otherwise list forms are committed through asynchronous XmlHttpRequests, and redirect options are not available.

CancelWithRedirectUrl - DOES NOT WORK

The following code does function:

properties.RedirectUrl = "http://www.google.com";
properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
Compiler is issuing the following warning:
'Microsoft.SharePoint.SPEventReceiverStatus.CancelWithRedirectUrl' is obsolete: '"Default list forms are committed through asynchronous XmlHttpRequests, so redirect urls specified in this way aren't followed by default. In order to force a list form to follow a cancelation redirect url, set the list form web part's CSRRenderMode property to CSRRenderMode.ServerRender"'. If you need to figure out how to set CSRRenderMode.ServerRender property for the form automatically (in list definition), please refer to my other blog post

SPUtility.Redirect - DOES NOT WORK

SPUtility.Redirect does not work in Event Receivers any more. It actually throws an exception. The reason - SPUtility.Redirect relies on HttpContext.Current, which does not exist at that point of execution. Tested with different CSRRenderMode settings.

[SubsetCallableExcludeMember(SubsetCallableExcludeMemberType.UnsupportedExternalType)]
public static bool Redirect(string url, SPRedirectFlags flags, HttpContext context, string queryString)
{
    string urlRedirect = null;
    bool flag = DetermineRedirectUrl(url, flags, context, queryString, out urlRedirect);
    if (flag)
    {
        bool flag2 = SPRedirectFlags.DoNotEndResponse == (flags & SPRedirectFlags.DoNotEndResponse);
        bool flag3 = DeltaPage.IsDeltaRedirectDisabled(context);
        if (!flag3 && DeltaPage.IsRenderingDelta(context))
        {
            DeltaPage handler = context.Handler as DeltaPage;
            if (handler != null)
            {
                handler.Redirect(context, urlRedirect, !flag2);
            }
            return flag;
        }
        bool flag4 = ((!flag3 && IsMDSEnabled(context)) && (!IsDialogUrl(urlRedirect) && IsBrowserRequest(context.Request))) && (SPRedirectFlags.AttemptMDSNavigate == (flags & SPRedirectFlags.AttemptMDSNavigate));
        bool flag5 = false;
        if (flag4)
        {
            flag5 = DeltaPage.AttemptMDSRedirect(context, urlRedirect, !flag2);
        }
        if (flag4 && flag5)
        {
            return flag;
        }
        SPLongOperation currentLongOperation = SPLongOperation.CurrentLongOperation;
        if (currentLongOperation != null)
        {
            currentLongOperation.End(url, flags, context, queryString);
            return flag;
        }
        if (Utility.IsClientQuery(context) && !Utility.IsRedirectAllowed(context))
        {
            RedirectException exception = new RedirectException(urlRedirect);
            context.Items[typeof(RedirectException)] = exception;
            throw exception;
        }
        try
        {
            context.Response.Redirect(urlRedirect, !flag2);
        }
        catch (Exception exception2)
        {
            if ((exception2 is ThreadAbortException) && !flag2)
            {
                throw;
            }
            ULS.SendTraceTag(0x62613371, ULSCat.msoulscat_WSS_Runtime, ULSTraceLevel.Medium, "Redirect to {0} failed. Exception: {1}", new object[] { url, exception2.ToString() });
        }
    }
    return flag;
}


internal static bool IsMDSEnabled(HttpContext ctx)
{
    return (((((ctx != null) && !DeltaPage.IsStartPage) && (!SPMobileUtility.IsMobilePageRequest(ctx, ctx.Request.Browser) && (ContextCompatibilityLevel >= 15))) && ((SPContext.Current != null) && (SPContext.Current.Web != null))) && SPContext.Current.Web.EnableMinimalDownload);
}


public static bool IsStartPage
{
    get
    {
        return IsMDSStartPageUrl(SPAlternateUrl.ContextUri.AbsolutePath);
    }
}


public static Uri ContextUri
{
    get
    {
        return GetContextUri(HttpContext.Current); //Here it throws an exception
    }
}

WORKING SOLUTION:

_currentContext.Response.Redirect

_currentContext.Response.Redirect does work though (IMPORTANT: Only when the form, which initiates an event, is being rendered in CSRRenderMode.ServerRender mode.) You can use the following sample:

public class TestEventHandler : SPItemEventReceiver
 {
  private readonly HttpContext _currentContext;
  public TestEventHandler()
  {
   _currentContext = HttpContext.Current;
  }
  // Methods
  public override void ItemAdding(SPItemEventProperties properties)
  {
   var url = new StringBuilder("test.aspx");
   string urlRedirect = null;
   bool flag = SPUtility.DetermineRedirectUrl(url.ToString(), SPRedirectFlags.RelativeToLayoutsPage, _currentContext, null, out urlRedirect);
   _currentContext.Response.Redirect(urlRedirect, true);
  }
 }