1
votes

I'm in the process of migrating some Sharepoint sites from one farm to another farm. It's a little more complicated, but for simplicity sake...

What I'd like to maintain is old URLs that people have for these sites, documents, etc. and the IIS URL Rewrite Module seems like a good way to go.

Here's an idea of what the structure is:

_______________________         _______________________
|oldfarm.company.com**|         |newfarm.company.com**|
|oldsitecollection**  |         |newsitecollection**  |
|subsitename          |         |subsitename          |
|...                  |         |...                  |
|_____________________|         |_____________________|

** = changes, everything else remains the same, URLwise.

On the "newfarm" I have extended the web application to respond to "oldfarm.company.com", and that web application has a URL Redirect Rule that redirects http://oldfarm.company.com/oldsitecollection/... to http://newfarm.company.com/newsitecollection/...

That works great for the vast majority of what I'm trying to do.

What I'm having difficulty with is rewriting QUERYSTRING values. Sharepoint's Office Document Viewers contain path information in the QUERYSTRING and that's what I need to change.

Here is an original URL sample: http://oldfarm.company.com/oldsitecollection/subsitename/_layouts/WordViewer.aspx?id=/oldsitecollection/subsitename/doclib/doc.docx&Source=http%3A%2F%2Foldfarm%2Ecompany%2Ecom%2Foldsitecollection%2Fsubsitename%2Fdoclib%2FForms%2FAllItems%2Easpx&DefaultItemOpen=1

Here is the URL after the redirect (and where I'm stuck): http://newfarm.company.com/newsitecollection/subsitename/_layouts/WordViewer.aspx?id=/oldsitecollection/subsitename/doclib/doc.docx&Source=http%3A%2F%2Foldfarm%2Ecompany%2Ecom%2Foldsitecollection%2Fsubsitename%2Fdoclib%2FForms%2FAllItems%2Easpx&DefaultItemOpen=1

Here is what I need the URL to look like: http://newfarm.company.com/newsitecollection/subsitename/_layouts/WordViewer.aspx?id=/newsitecollection/subsitename/doclib/doc.docx&Source=http%3A%2F%2Fnewfarm%2Ecompany%2Ecom%2Fnewsitecollection%2Fsubsitename%2Fdoclib%2FForms%2FAllItems%2Easpx&DefaultItemOpen=1

I have tried using Rewrite Maps because these are not dynamic substitutions, but I cannot get them to modify the QUERYSTRING.

Here's an example of the rewrite rule I'm working on:

<rewrite>
    <rewriteMaps>
        <rewriteMap name="WordViewer">
            <add key="id=/oldsitecollection" value="id=/newsitecollection" />
        </rewriteMap>
    </rewriteMaps>
    <rules>
        <rule name="Rewrite rule1 for WordViewer">
            <match url=".*WordViewer.aspx" />
            <conditions>
                <add input="{WordViewer:{QUERY_STRING}}" pattern="(.+)" />
            </conditions>
            <action type="Rewrite" url="{C:1}" appendQueryString="false" />
        </rule>
    </rules>
</rewrite>
1

1 Answers

1
votes

To answer my own question, what worked for me was to create my own custom rewrite provider.

The provider I created was a simple find/replace provider that looked like this:

public class FindReplaceProvider : IRewriteProvider, IProviderDescriptor
{
    public string Find { get; private set; }
    public string Replace { get; private set; }

    public void Initialize(IDictionary<string, string> settings, IRewriteContext rewriteContext)
    {
        string tmpFind, tmpReplace;

        if (!settings.TryGetValue("Find", out tmpFind) || string.IsNullOrEmpty(tmpFind))
            throw new ArgumentException("FindReplaceProvider setting 'Find' is required and cannot be empty");

        if (!settings.TryGetValue("Replace", out tmpReplace))
            throw new ArgumentException("FindReplaceProvider setting 'Replace' is required and cannot be null");

        if (!string.IsNullOrEmpty(tmpFind))
            Find = tmpFind;
        else
            throw new ArgumentException("FindReplaceProvider parameter 'Find' cannot be empty");

        if (!string.IsNullOrEmpty(tmpReplace))
            Replace = tmpReplace;
        else
            Replace = String.Empty;
    }

    public string Rewrite(string value)
    {
        return Regex.Replace(value, Find, Replace, RegexOptions.IgnoreCase);
    }

    public IEnumerable<SettingDescriptor> GetSettings()
    {
        yield return new SettingDescriptor("Find", "String to find");
        yield return new SettingDescriptor("Replace", "String to replace");
    }
}

And my rewrite rules end up looking like this:

<rewrite>
  <providers>
    <provider name="OfficeWebAppsReplaceId" type="MyFindReplaceProvider">
      <settings>
        <add key="Find" value="id=/oldsitecollection" />
        <add key="Replace" value="id=/newsitecollection" />
      </settings>
    </provider>
    <provider name="OfficeWebAppsReplaceSource" type="MyFindReplaceProvider">
      <settings>
        <add key="Find" value="http%3A%2F%2Foldfarm%2Ecompany%2Ecom%2Foldsitecollection%2" />
        <add key="Replace" value="http%3A%2F%2Fnewfarm%2Ecompany%2Ecom%2Fnewsitecollection%2" />
      </settings>
    </provider>
  </providers>
  <rules>
    <rule name="OfficeWebAppsQuerystringRedirect" stopProcessing="true">
      <match url=".*(WordViewer.aspx|WordEditor.aspx|xlviewer.aspx|PowerPoint.aspx)$" />
      <conditions logicalGrouping="MatchAny">
        <add input="{QUERY_STRING}" pattern=".*id=/oldsitecollection.+" />
        <add input="{QUERY_STRING}" pattern=".*Source=http%3A%2F%2Foldfarm%2Ecompany%2Ecom%2Foldsitecollection%2F.+" />
      </conditions>
      <action type="Redirect" url="{R:0}?{OfficeWebAppsReplaceId:{OfficeWebAppsReplaceSource:{C:0}}}" appendQueryString="false" redirectType="Temporary" />
    </rule>
  </rules>
</rewrite>