The Content Editor Web Part (CEWP) shipped with SharePoint 2007 is just one of these ordinary Web Parts: they don't introduce any extraordinary functionality, yet we all use them in our solutions for some reason. Because this Web Part is all about displaying the Rich Text you have entered, you might think, that it is almost impossible to mess that up. Unfortunately…
The problem about using the Content Editor Web Part is that it makes absolute URL of all the relative ones you have entered. What's the problem? – you might think. Imagine that you have separate editors environment – where the content is being edited, and a public site with anonymous access. If you're not using the Content Deployment the public site is very likely to be an extended version of the editors Web Application. How would you feel if all the links would point to the editors Web Application where you have to login instead of the public one?
For those of you who have worked with the Content Editor Web Part for a while now it's probably nothing new. While in general it wouldn't be particularly difficult to override this behavior, the ContentEditorWebPart is sealed – you cannot extend it nor modify it. While building your own alternative might be an option there is another way to solve this issue using Control Adapters.
Control Adapters have been introduced in the ASP.NET 2.0 framework as an extra layer of logic which can be used to override the way the presentation layer is being rendered. By benefiting of that concept you can create your control once and reuse it in every project you will ever work on by modifying the presentation layer with Control Adapters.
Because the ContentEditorWebPart is sealed you cannot extend it. You are still able though, to create a custom Control Adapter which will apply the required modification. In our case it will make all URLs relative.
The Concept
The idea of the custom Control Adapter for the Content Editor Web Part is very simple: hookup to the Content Editor Web Part, intercept the HTML rendered by the Web Part, turn all absolute URLs into relative and render the output.
ContentEditorWebPartAdapter
public class ContentEditorWebPartAdapter : ControlAdapter { protected override void Render(System.Web.UI.HtmlTextWriter writer) { StringBuilder sb = new StringBuilder(); HtmlTextWriter htw = new HtmlTextWriter(new StringWriter(sb)); base.Render(htw); // make all URLs relative Regex regex = new Regex( "((?:href|src)=\")https?://[^/]+([^\"]+\")"); string output = regex.Replace(sb.ToString(), "$1$2"); writer.Write(output); } }
That's really all. First of all you get the rendered output. It's being stored in the sb StringBuilder. Then you make all absolute URLs relative. While you could use the standard String.Replace to improve the overall performance of this routine, I have chosen for the Regular Expressions to make it a bit more safe and reusable. The last step is writing the output back on the page.
Linking the ContentEditorWebPartAdapter to the Content Editor Web Part
The next thing to do is to attach the custom Control Adapter we have just created to the Content Editor Web Part. You do this by creating a .browser (for example Imtech.browsers) file in the App_Browsers directory of your Web Application. This file has to contain the following:
<browsers> <browser refID="Default"> <controlAdapters> <adapter controlType="Microsoft.SharePoint.WebPartPages.ContentEditorWebPart" adapterType="Imtech.SharePoint.Adapters.ContentEditorWebPartAdapter" /> </controlAdapters> </browser> </browsers>
The controlType attribute defines the type you want to attach to (Content Editor Web Part in our case) and the adapterType defines the full name of our custom Control Adapter. Since I have deployed it to the bin directory, the full type name is sufficient. On the other hand you might want this to make part of your existing assembly residing in GAC. In such case you have to extend the adapterType definition with the fully qualified name including the Public Key Token.
Wait! We're using SharePoint
In a plain ASP.NET application that would be sufficient. However, since we're using SharePoint you have to apply some modifications to the web.config. You have to allow your custom Control Adapter to access the SharePoint API. To do that you either have to set the trust to Full or create a Code Access Policy. As I know my own code and I definitely trust it, I have chosen for the first approach.
Summary
The Content Editor Web Part is a very convenient control which allows the end users to put on the pages some extra information which doesn't necessary have to be a part of the particular Content Type. In spite of the fact that the CEWP turns all relative URLs into absolute and cannot be extended there are some possibilities to override the default behavior and keep using the Web Part on extended Web Applications. The concept of Control Adapters suits this situation perfectly and is definitely an efficient alternative comparing to creating your own Web Part.




July 14th, 2008 at 9:58 am
I'm trying to use your solution, but I can't get the RegEx to work in a simple test harness. It always seems to return whatever the input string was.
July 14th, 2008 at 10:31 am
Hello Tom. Thank you for your feedback. There seems to be a problem with the quotes in the code snippets. WordPress – my blogging platform, automatically turns them into curly quotes. You have to replace them with plain quotes before using in the code. I will try to fix the issue on the blog as soon as possible.
July 16th, 2008 at 6:20 pm
I'm having trouble getting this to work. It seems to me that my .browser file is simply not being accessed. I get no errors, but the content is not changed at all. Any troubleshooting suggestions?
July 16th, 2008 at 6:23 pm
1. Have you increased the trust level or added a custom CAS policy?
2. Have you added the SafeControl directive for the assembly?
3. Have you emptied the temporary ASP.NET directory?
July 16th, 2008 at 10:32 pm
Ahhh… the cache was the culprit. Now I\'m at least getting errors so I have something to chase down! :-) Thanks!
July 17th, 2008 at 5:35 pm
Got it working! Except for some reason when I deploy this as a solution, adding a reference to the assembly in the SafeControls section of the Web.Config, it fails to find the assembly. If I manually add a line to the Assemblies section of the web.Config it works just fine.
Any clue why? Does it have anything to do with the .browsers file be accessed by IIS rather than the Sharepoint application?
July 17th, 2008 at 8:54 pm
I would say that the required things are:
- SafeControl entry in the web.config
- .browser file in the App_Browsers directory
- Application Pool account (of the current account if you're using impersonation) having access to the .browser file
The .browser files are getting cached so in some scenario's it is required to empty the ASP.NET temp directory.
You could try to experiment with different approaches to find which one of the actually stops it from working.
August 25th, 2008 at 10:20 am
"Wait! We're using SharePoint", it is more complex…
You can place .browser file in a SharePoint Web Application folder. But what if you're running with multiple front end machines. You've to place the .browser file in all web application folders on all front end machines.
And when you decide to turn on a new front-end machine then you've to place the .browser file manually on the new front-end! This isn't a quite elegant solution.
August 25th, 2008 at 4:51 pm
That's why it is useful to deploy .browser files using for example Web Application scoped Features. As soon as you add a new server to the Farm the Features and so the .browser files will automatically get deployed.
August 28th, 2008 at 11:49 am
When I \"Create a new or extend a Web Application\" then the Features scoped for a Web Application will be activated. Later on when I choose to activate a new Web Front End Server then the Web Application is already there and so the feature will not be activated again. Correct me if I am wrong.
August 29th, 2008 at 6:24 am
As far as I know you will have to deploy the Web Application one way or the other to the new server, right? I would say that that's the moment when your .browser files will get deployed.
August 29th, 2008 at 1:03 pm
I will give it a try. But at this moment I don't have a Front End machine to test it. How can I add a browser file to the web application App_Browsers folder using a feature scoped WebApplication?
Feature.xml:
Elements.xml:
…..How to deploy a browser file?….
August 29th, 2008 at 1:04 pm
My feature.xml is removed by the blog software…
August 29th, 2008 at 1:47 pm
AFAIK it can be done only programmatically. Using FeatureReceivers I determine the physical path of the Feature where the .browser files are. Then using File.Copy() method you can copy all the .browser files to the IIS Web App directory.
September 23rd, 2008 at 4:02 pm
File.Copy() works for now, but when I add a new web front end, the FeatureReceivers scoped for a WebApplication do not execute again…
So you're new web front end machine is not synchrone with the other front ends. So you've to copy the browser file(s) manually.
December 30th, 2008 at 2:27 am
Thanks Waldek. This is a great post dude.
December 30th, 2008 at 7:16 am
@Nasser: You're welcome :)
January 20th, 2009 at 3:47 am
FeatureRecievers only fire once (not per web front end when added) there is actually no way to copy the .browser file into the inetpub hive except for the application to periodically check to see if its there, and if its not then copy it.
January 28th, 2009 at 6:30 pm
Hi Waldek,
the CONTENT link property which is really not stored as absolute URL when I deploy from one box to other. Basically it shows me the same relative path. My problem is it wants the path from the root, so for e.g.: if you have a site collection at http://myRootSiteCollection.com/ and we have a Pages library containing the content html, I would give the link for CONTENT LINK property as: "/Pages/MyContentPage.html". Now when I export and save the web part on a different site-collection with a managed path, so for e.g. http://myRootSiteCollection/sites/myOtherSiteCollection the Content link path still shows in the Content Link property as “/Pages/MyContentPage.html” and it doesn’t work and if now I change it to “/sites/myOtherSiteCollection/Pages/MyContentPage.html” and it works. So as you mentioned CEWP maintains the paths as absolute paths do you also mean that it maintains the web-part properties also as absolute path as CONTENT LINK is a web part property?
And if it does then does the adaptor convert these urls also?
January 29th, 2009 at 1:50 pm
@MossBuddy: As far as I can tell you could make the Control Adapter translate the Site Collection URL's so that they work when moved to another Site Collection which URL is other than '/'. Using a Regular Expression you could grab all URL's which begin with a '/' and then prepend them with the URL of your Site Collection.
March 17th, 2009 at 11:07 pm
Waldek I think I'm stuck. So I linked the adapter to the webpart and made my code. Where do I put my code? I noticed you said you deployed it to the "bin" folder, but I'm getting an error "Could not load type 'CEWPUrl.SharePoint.Adapters.ContentEditorWebPartAdapter'".
March 17th, 2009 at 11:40 pm
@Jax: there are a couple approaches out there. First of all, if you have worked with AKS you might've noticed that they don't compile the classes and put the .cs files in the App_Code folder of your Web Application. That's one. Another approach is to create an assembly including your classes and then put it either in the bin directory of your Web Application or deploy it to the Global Assembly Cache. The latest will make it available for all Web Applications on the server – useful if you would like to reuse it across multiple Web Applications. Does this make more sense?
March 17th, 2009 at 11:43 pm
Yes! Thank you very much for the fast response. Great job on the article.
March 18th, 2009 at 8:18 am
@Jax: Thank you for the feedback, I appreciate it.
March 18th, 2009 at 6:03 pm
Waldek, I apologize, but I have one more question. I have added my dll to the bin folder with your code and my namespace is named "CEWP", I have also added the code to the compat.browser and added a "SafeControl" and an "Add Assembly" to the web.config, but still get a 'Could not load file or assembly 'CEWP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=########' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.'
Any Ideas?
March 18th, 2009 at 10:15 pm
@Jax: there are two things that have to fully match: the reference in the .browser file and the safe control directive. Could you post the content of .browser and the safecontrol line, and confirm that they both point to the same full class name (namespace.class) as defined in your assembly?
March 18th, 2009 at 10:49 pm
It worked! YOU ROCK! Thanks Waldek!! I've been working on it all day…
March 18th, 2009 at 10:54 pm
@Jax: Great to hear I could help :)
March 24th, 2009 at 6:26 pm
Waldek,
Now that I have it working on one site, how do you suggest deploying it to the GAC? MSI, gacutil, or manual copy? Also, once we create a new web app do we have to manually update the compat.browser each time?
Thanks again!
March 25th, 2009 at 8:30 am
You can deploy the assembly either to bin of you Web Application, GAC or App_Code – it doesn't really matter. As for the .browser: you could deploy it using a Feature Receiver hooked up to the FeatureActivated event. The only time this doesn't work is when you add a new server to the Farm. In such scenario you would have to deploy the .browser file manually.
March 27th, 2009 at 5:34 pm
Hey Waldek,
I\'m sorry to keep bothering you, but am totally stuck again. So I got my .dll to work great in the bin folder but, for the life of me, cannot get it to find it in the GAC. I keep getting a \"Can not load type\" error. Any ideas? Once I move it back into the bin it works fine.
March 28th, 2009 at 2:29 pm
@Jax: if you move your assembly to the GAC, you have to be sure that the assembly name is a fully qualified (4-part) name including PublicKeyToken
May 20th, 2009 at 6:35 pm
Waldek, we are getting the following error when trying to implement this. Details:
Here are some details on the setup we have done…
Safe Control entry in web.config:
<safecontrol Assembly="ContentEditorWebPartAdapter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=###########" Namespace="ContentEditorWebPartAdapter" TypeName="*" Safe="True" />
ContentEditorWebPartAdapter.browser file:
<browsers>
<browser refID="Default">
<controladapters>
<adapter controlType="Microsoft.SharePoint.WebPartPages.ContentEditorWebPart"
adapterType="ContentEditorWebPartAdapter" />
</controladapters>
</browser>
Error:
Server Error in '/' Application.
——————————————————————————–
Server could not create ContentEditorWebPartAdapter.ContentEditorWebPartAdapter.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Exception: Server could not create ContentEditorWebPartAdapter.ContentEditorWebPartAdapter.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[Exception: Server could not create ContentEditorWebPartAdapter.ContentEditorWebPartAdapter.]
System.Web.Configuration.HttpCapabilitiesBase.GetAdapterFactory(Type adapterType) +468
System.Web.Configuration.HttpCapabilitiesBase.GetAdapter(Control control) +8719162
System.Web.UI.Control.ResolveAdapter() +77
System.Web.UI.Control.InitRecursive(Control namingContainer) +19
System.Web.UI.Control.AddedControl(Control control, Int32 index) +198
System.Web.UI.ControlCollection.Add(Control child) +80
System.Web.UI.WebControls.WebParts.WebPartManagerControlCollection.AddWebPartHelper(WebPart webPart) +220
System.Web.UI.WebControls.WebParts.WebPartManagerControlCollection.AddWebPart(WebPart webPart) +108
System.Web.UI.WebControls.WebParts.WebPartManager.AddWebPart(WebPart webPart) +55
System.Web.UI.WebControls.WebParts.WebPartManagerInternals.AddWebPart(WebPart webPart) +11
Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddWebPartWithRetry(WebPart webPart) +168
Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddDynamicWebPart(WebPart webPart) +85
Microsoft.SharePoint.WebPartPages.SPWebPartManager.CreateWebPartsFromRowSetData(Boolean onlyInitializeClosedWebParts) +7855
Microsoft.SharePoint.WebPartPages.SPWebPartManager.LoadWebParts() +63
Microsoft.SharePoint.WebPartPages.SPWebPartManager.OnPageInitComplete(Object sender, EventArgs e) +409
System.EventHandler.Invoke(Object sender, EventArgs e) +0
System.Web.UI.Page.OnInitComplete(EventArgs e) +8698006
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +467
——————————————————————————–
Thanks in advance for any help you can provide
-Erin
May 20th, 2009 at 7:24 pm
@Erin: Have you tried changing the value of adapterType attribute to "ContentEditorWebPartAdapter.ContentEditorWebPartAdapter"? It seems like you're adapter class is called ContentEditorWebPartAdapter and it's stored in the ContentEditorWebPartAdapter namespace. That makes it double.
May 20th, 2009 at 7:35 pm
Hi – yes we have tried that as well
thanks,
erin
May 20th, 2009 at 8:06 pm
@Erin: have you tried clearing the ASP.NET cache? Additionally could you post the code of your adapter?
May 20th, 2009 at 8:26 pm
We did clear the cache — here is the code:
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.Adapters;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
namespace ContentEditorWebPartAdapter
{
class ContentEditorWebPartAdapter : ControlAdapter
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
StringBuilder sb = new StringBuilder();
HtmlTextWriter htw = new HtmlTextWriter(new StringWriter(sb));
base.Render(htw);
// make all URLs relative
Regex regex = new Regex(
\"((?:href|src)=\\\")https?://[^/]+([^\\\"]+\\\")\");
string output = regex.Replace(sb.ToString(), \"$1$2\");
writer.Write(output);
}
}
}
May 20th, 2009 at 8:51 pm
@Erin: What trust lavel have you set in web.config?
May 20th, 2009 at 8:53 pm
Full trust -
May 20th, 2009 at 10:21 pm
@Erin: that's odd indeed… what you could try is not to compile the adapter's code and put it in App_Code instead, just to check whether it's code/loading assembly that's failing or something else. This approach is used in AKS by the way (for some extra reference if you don't exactly know how it works).
May 21st, 2009 at 10:06 pm
Hi there – we redid the whole thing — here is our new error, this may shed more light on our issue:
This time I changed the .browser file to following:
<browsers>
<browser refID=\"Default\">
<controlAdapters>
<adapter
controlType=\"Microsoft.SharePoint.WebPartPages.ContentEditorWebPartAdapter\"
adapterType=\"ContentEditorWebPartAdapter.ContentEditorWebPartAdapter\" />
</controlAdapters>
</browser>
</browsers>
Error has changed to following:
Server Error in \'/\' Application.
——————————————————————————–
Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.
Parser Error Message: Could not load type \'Microsoft.SharePoint.WebPartPages.ContentEditorWebPartAdapter\'.
Source Error:
Line 2: <browser refID=\"Default\">
Line 3: <controlAdapters>
Line 4: <adapter
Line 5: controlType=\"Microsoft.SharePoint.WebPartPages.ContentEditorWebPartAdapter\"
Line 6: adapterType=\"ContentEditorWebPartAdapter.ContentEditorWebPartAdapter\" />
Source File: C:\\Inetpub\\wwwroot\\wss\\VirtualDirectories\\80\\App_Browsers\\ContentEditorWebPartAdapter.browser Line: 4
——————————————————————————–
May 22nd, 2009 at 12:29 am
@Erin: The Microsoft.SharePoint.WebPartPages namespace doesn't contain a ContentEditorWebPartAdapter class. The controlType attribute must point to the full name of the control/web part to which you want to attach the adapter: Microsoft.SharePoint.WebPartPages.ContentEditorWebPart in our case.
July 1st, 2009 at 10:06 am
Hey Waldek,
thanks for sharing us this information , but i have a quesion not related to this subject ,i'm new in regular expresion and try to use your one to add Http://xxx to any absolute url in my string and this is my code
string body ="<a class=ms-sitemapdirectional href=\"/\">GDI</a><a class=ms-sitemapdirectional href=\"/ENGLISH/Pages/default.aspx\">English</a><a class=ms-sitemapdirectional href=\"/English/Media_Center/Pages/redirect1.aspx\">Media Center</a>";
Regex regex = new Regex("((?:href|src)=\")http?://[^/]+([^\"]+\")");
string output = regex.Replace(body, "http://www.gdi.com");
but it doesn't replace any thing
could you please advice me to right regular expresion
July 1st, 2009 at 5:36 pm
@Quasem: I'm not sure why you're Regex isn't working, but I managed to create another one which should do the job. The Regex is ((?:href|src)=")([^h][^"]*)(")
And the replace is $1http://www.gdi.com$2$3
July 2nd, 2009 at 9:33 am
Thanks Waldek for your fast reply.. your regex working fine and this another way i found it during my search yestarday..
public static String ConvertRelativePathsToAbsolute(String text, String absoluteUrl)
{
String value = Regex.Replace(text,
\"<(.*?)(src|href)=\\\"(?!http)(.*?)\\\"(.*?)>\",
\"<$1$2=\\\"\" + absoluteUrl + \"$3\\\"$4>\",
RegexOptions.IgnoreCase | RegexOptions.Multiline);
return value.Replace(absoluteUrl + \"/\", absoluteUrl);
}
any way .. thanks a lot for your help and support :) (F)
July 3rd, 2009 at 1:43 pm
Hi Waldek,
I am using ur solution.
For me everything works fine if .browser file is manually copied.
But the problem starts when .browser file is deployed using feature receiver (to copy .browser file from 12 hive), the content editor still shows the absolute paths…
also the same wont work if xcopy is used to copy .browser.
did anyone face the same issue?
any help will be appreciated.
July 4th, 2009 at 12:18 pm
@Vinod: Perhaps the ASP.NET cache is not getting refreshed? Have you tried deleting all files in the ASP.NET Temporary Files folder after copying the .browser file?
August 13th, 2009 at 8:10 pm
I noticed that your regex solution changes ALL absolute URLs. Even the domains of external links. This is something to be careful when used with the CEWP.
August 13th, 2009 at 8:26 pm
@Dave: you're right. In a real life scenario you would either retrieve the URL's from SharePoint or to gain even more performance include them in your code.
August 26th, 2009 at 9:22 am
I really need this solution, but my understanding on Sharepoint was not up to the level. Could you provide us with a script file that can be downloaded.
Step by step explanation will be great.
Your assistance is very much appreciated.
August 26th, 2009 at 6:57 pm
@Lukman: making the above work isn't as difficult as it might seem. Have you already read some articles about how Control Adapters work? Do you have some specific questions or are you stuck at some point? Let me know and I'd be glad to help you out.
August 27th, 2009 at 2:52 am
Hi Waldek,
Thanks for the fast response.
I add reference to the project as well as include \"using Microsoft.Sharepoint\" below, however I received these error when I compiled the code:
The type or namespace name \'ControlAdapter\' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name \'UI\' does not exist in the namespace \'System.Web\' (are you missing an assembly reference?)
Here is the code:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
namespace IMC.WebPartAdapter
{
public class ContentEditorWebPartAdapter : ControlAdapter
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
StringBuilder sb = new StringBuilder();
HtmlTextWriter htw = new HtmlTextWriter(new StringWriter(sb));
base.Render(htw);
// make all URLs relative
Regex regex = new Regex(
\"((?:href|src)=\\\")https?://[^/]+([^\\\"]+\\\")\");
string output = regex.Replace(sb.ToString(), \"$1$2\");
writer.Write(output);
}
}
}
August 27th, 2009 at 4:46 pm
@Lukman: as the error message says: have you added a reference to System.Web.dll in your project?
August 28th, 2009 at 3:42 am
@Waldek: After adding reference to System.Web, one of the error disappear. But the other error "The type or namespace name \'ControlAdapter\' could not be found (are you missing a using directive or an assembly reference?)" still remains.
May I know what are the necessary dll needed to be referenced? Thanks.
August 28th, 2009 at 6:17 am
@Lukman: The ControlAdapter class is in the System.Web.UI.Adapters namespace so you have to add 'using System.Web.UI.Adapters' at the top of your code file.
August 28th, 2009 at 6:23 am
@Waldek: Yes, I have tried that, but ended up there are more errors. Thanks for your assistance.
The type or namespace name 'HtmlTextWriter' could not be found
The type or namespace name 'StringWriter' could not be found
The best overloaded method match for 'System.Web.UI.Adapters.ControlAdapter.Render(System.Web.UI.HtmlTextWriter)' has some invalid arguments
Argument '1': cannot convert from 'HtmlTextWriter' to 'System.Web.UI.HtmlTextWriter'
The type or namespace name 'Regex' could not be found
August 28th, 2009 at 6:30 am
@Lukman: as you're getting all these errors I'm assuming that you're using a non-compiled .cs file in the App_code folder of your Web Application, am I right? If so, try to put the code in a Class Library Visual Studio Project: it will make it easier for you to get all the references to the missing namespaces. Please note that Visual Studio provides Visual Hints for non-resolves class names when you move the cursor to such class name.
August 28th, 2009 at 7:19 am
@Waldek: I created a project to build this class. Which Web Application are you referring to? I do not have any Web Application other than Sharepoint 2007.
August 28th, 2009 at 11:38 am
@Lukman: Web Application meaning IIS Site
September 11th, 2009 at 10:29 pm
How to debug control adapter with visual studio?
September 11th, 2009 at 10:34 pm
@Constantin: If I'm right you can only do this if you're using an assembly. You cannot attach debugger if you're using an uncompiled Control Adapter in the App_Code directory.
December 17th, 2009 at 1:30 pm
Hi,
we noticed this problem with upgrading extranet from http to https. It also occures on content query webpart. Do you think your adapter solutution will work with th cqwp?
December 17th, 2009 at 2:04 pm
@Sander: You can attach a Control Adapter to any ASP.NET control so the CQWP is no exception here.
December 27th, 2009 at 12:42 am
Dear Waldek,
thank you for sharing and for your continous support,
As Dave mentioned the absolute URLs will got modified too, u suggeted to [retrieve the URL's from SharePoint or to gain even more performance include them in your code], can you please explain whats meant by that, how shall i include my Absolute URL with in the context of CEWP without it being modified?
Thank You,
Fuad
December 29th, 2009 at 8:34 am
@Fuad: I think that Dave mentioned something else, meaning that the solution would process all absolute URL's and not only those that belong to your Web Application. While replacing the URL's you can either programmatically retrieve the server part for the different zones or you could just hardcode it in your code which would be obviously faster.
January 25th, 2010 at 10:10 pm
Hi Waldek,
I have been trying to make your solution work for my scenario but I have not been successfull. I have WIndows Authentication Site and Extended Anonymous Site.
On the Anonymous Site the link to images/documents show the Windows Authentication Site. However when I debug after deploying the your source code I see the URL's are getting corrected to relative url's but after the page renders the url's still poin to windows authentication. PLEASE HELP! What am I doing wrong?
Note: I have cleared the ASP.NET cache after deploying browser file. I am deploying the dll to GAC and .browser file is in IIS web application directory.
January 25th, 2010 at 10:12 pm
Hi Waldek,
I have deployed the DLL to GAC and .browser file to web application directory. However when I debug attachign the process I can see the uRL's are corrected to relative paths. However after the page render process I still the url's pointing to the windows authentication site on my extended anonymous site.
PLEASE help!
January 26th, 2010 at 5:15 pm
@Amit: Have you change anything about the code of the Control Adapter?
February 25th, 2010 at 7:51 am
Hello Waldek,
Your solution seems amazing ! Unfortunatelly, I dont have so much experience with compiling code and I really have no idea how to do it.
Could you please help me to implement your feature?
Thank you for your help
February 28th, 2010 at 1:45 pm
@Benoit: no problem. What is it that you're struggling with?
March 2nd, 2010 at 4:08 am
Thank you very for your help,
Well, if I understand correctly, I need to create a DLL thanks to the code that you provide on your website. I created a ASP.NET Server Control, add the different References (included the Microsoft.Sharepoint that I retrieve from Common Files\Microsoft Shared\web server extensions\12\ISAPI and System.Text.RefularExpressions in order to make "Regex" working)
After compiling the code, I get the error "A project with an Output Type of Class Library cannot be started directly)
I'm pretty sure that it is a small issue and I'm really sorry to disturb you for such little thing but I'm really not good at developing stuff.
Thank you in advance for your help and your time,
Regards,
Ben
March 2nd, 2010 at 4:08 am
Thank you very for your help,
Well, if I understand correctly, I need to create a DLL thanks to the code that you provide on your website. I created a ASP.NET Server Control, add the different References (included the Microsoft.Sharepoint that I retrieve from Common Files\Microsoft Shared\web server extensions\12\ISAPI and System.Text.RefularExpressions in order to make "Regex" working)
After compiling the code, I get the error "A project with an Output Type of Class Library cannot be started directly)
I'm pretty sure that it is a small issue and I'm really sorry to disturb you for such little thing but I'm really not good at developing stuff.
Thank you in advance for your help and your time,
Regards,
Ben
March 2nd, 2010 at 4:10 am
Thank you very for your help,
Well, if I understand correctly, I need to create a DLL thanks to the code that you provide on your website. I created a ASP.NET Server Control, add the different References (included the Microsoft.Sharepoint that I retrieve from Common Files\Microsoft Shared\web server extensions\12\ISAPI and System.Text.RefularExpressions in order to make "Regex" working)
After compiling the code, I get the error "A project with an Output Type of Class Library cannot be started directly")
I'm pretty sure that it is a small issue and I'm really sorry to disturb you for such little thing but I'm really not good at developing stuff.
Thank you in advance for your help and your time,
Regards,
Ben
March 2nd, 2010 at 5:08 pm
@Ben: What you need to do is to build the assembly (in Visual Studio Build > Build project). Then you have to copy the built assembly (.dll) and copy it to the bin directory of your Web Application (..\inetpub\…\bin\). The last part is to create a file that will link the Control Adapter to the Content Editor Web Part. This is described in the last part of the article along with the XML snippet that you have to put in the file. Don't forget to change the contents of the adapterType attribute so that it points to your class name!
March 3rd, 2010 at 3:36 am
Waldek,
Thanks again for your help,
Right now, and after made all the changes, I retrieve an error everytime I try to use the ContentEditorWebPart :
"The "ContentEditorWebPart" Web Part appears to be causing a problem. Request for the permission of type 'Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=###########' failed."
Thank you again :)
Ben
April 21st, 2010 at 8:29 am
Mate, this looks fairly powerful if you can just use a reg exp to edit the output… Basically, I am thinking that you would be able to strip out non-compliant HTML formatting from the CEWP too. ie , etc etc.
Have you ever tried that kind of concept with your adapter?
April 22nd, 2010 at 2:38 pm
Waldek,
We have a problem about site variation,after we created the root site (en-US) and import(using import command) all the backup data from our old server and create another site variation like en-CA and start creating hierarchy an error occurred,the error message did not tell the specific error,is there a configuration which need to set to create the new variation site ,I know how to configure site variation like setting the root site,creating label etc….Is there any configuration need to be set in web.config etc..?
April 23rd, 2010 at 1:27 am
Thanks for this blog Waldek! This is very interesting… sounds like by using reg exp you could turn this into a very powerful control mechanism. Has you ever tried to use this to control the output of tags like or etc?
Cheers!
April 23rd, 2010 at 1:30 am
There are meant to be font and span tags in that last post! :)
April 23rd, 2010 at 1:39 pm
@Phil: I haven't done that myself, but it could be perfectly possible
April 23rd, 2010 at 1:40 pm
@Mel: this is a slightly off-topic question for this post… There is no specific configuration for working with variations except for the variation root and variation labels pages. What you could try is to run the variations fixup tool. Perhaps that would solve your problem.
June 4th, 2010 at 12:04 pm
[...] попробовать ControlAdapter как это описано в этой отличной статье чтобы добавить хотя бы кнопочку "Insert HTML" вроде той, что [...]
June 11th, 2010 at 8:12 am
I am getting error for <adapter controlType="Microsoft.SharePoint"
as Could not load type 'Microsoft.SharePoint' which is in .browser file any help
June 11th, 2010 at 8:24 am
@Rohit: you're missing a part of the full control name. Have a close look at the sample I provided above to get the exact controlType value.
June 16th, 2010 at 11:36 am
How can i change master page and pagelayout using PageAdapter?
September 17th, 2010 at 9:37 pm
Do The above solution help for Https FBA (form login sites).
I have a environment where the content editor webpart does not render on the https site..
Any clue ,really appriciate if some one share if they have encountered the same issue on sharepoint.
September 19th, 2010 at 1:59 pm
Hello, Waldek!
I recently used this solution for localization purposes, and all is working as expected now.
Only thing which is not mentioned in the article is the deployment of .webbrowser file. I used for this timer job, created when my deployment feature is activated.
So.. Great job! Thank you!
September 20th, 2010 at 8:12 am
@ SIMANTA: Please check the below experts exchange link.
http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/Server/MS-SharePoint/Q_24197262.html
October 27th, 2010 at 2:00 pm
Great work! Does it work on SharePoint 2010?
October 27th, 2010 at 9:20 pm
@Kaleu: Although I haven't tested it on SharePoint 2010 yet, it should work without any problems.
March 3rd, 2011 at 6:40 pm
in multi language provisionning page with cewp, can i set the ContentLink property like this /sireurl/~language/…
March 6th, 2011 at 5:12 am
@ahmed: I'm afraid you can't, at least not out of the box. What is your scenario exactly?
August 4th, 2011 at 8:23 pm
Hi Waldek,I am using Content Editor webpart in sharepoint 2010 to play video in youtube wat basically i do is get embded code from youtube and save it in .txt file within some library.Then insert content editor webpart and set contentLink to url of .txt file and its works fine but i am wondering if i can set the contentLink programatically so users don't have follow all steps.
please advise
Thanks
Ronak
August 5th, 2011 at 1:44 pm
@Ronak: You could try updating the value of the ContentLink property.
August 5th, 2011 at 2:13 pm
Thanks Waldek how can i do that using your example above.i need to write some business logic in order to get file from Document library.
August 6th, 2011 at 2:29 pm
@Ronak: Why would you want to do that? CEWP should do that automatically for you? Or are you concerned that the links in the text file you will be linking to will be rewritten as well?
September 12th, 2011 at 11:26 am
Hey i found good link which gave me answer
check out this one.
http://maulikdhorajia.blogspot.com/2011/09/override-content-query-webpart-to-do-on.html
September 26th, 2011 at 7:49 pm
I added the browser file at my web application level (inetpub)
I added the control adapter in the web.config as safe controls
Deleted the temporray files
added the necessary right to the application pool user for the App_browser folder.
But still the custom adapter is not activated when I run my sharepoint site.
Anything that i missed?
September 26th, 2011 at 9:19 pm
@Skander: Anything in the Error Viewer/ULS? Are you sure you mapped the Control Adapter type and the WP type correctly?
September 27th, 2011 at 9:30 am
Waldek, Excellent article.
I have question regarding a sharepoint site. I'm using the content editor web part for the front page of a site because it's easy to customise using HTML. However, I cannot seem to check out/in files in the CEWP? If a list then okay but not for CEWP. Is there a solution?
Cheers.
September 27th, 2011 at 9:51 am
@Hoss: I don't really understand what you mean. Content Editor Web Part only displays static HTML. It doesn't provide you with any functionality such as checking out files.
September 27th, 2011 at 7:06 pm
adapter controlType="System.Web.UI.WebControls.WebParts.WebPartZone"
adapterType="X.Y.ClientFramework.WebPartZoneControlAdapter, X.Y.ClientFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=d9755168a76daa9b"
September 27th, 2011 at 7:08 pm
web.config/safe controls:
SafeControl Assembly="X.Y.ClientFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=d9755168a76daa9b" Namespace="X.Y.ClientFramework" TypeName="*" Safe="True" SafeAgainstScript="True"
SafeControl Assembly="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" Namespace="System.Web.UI.WebControls.WebParts" TypeName="WebPartZone" Safe="True" AllowRemoteDesigner="True" SafeAgainstScript="True"
September 28th, 2011 at 3:35 pm
@Skander: Looks okay to me. Another thing that you could try to do, to trigger rebuilding Control Adapters, would be to "touch" (ie. add somewhere a space, save the file and then remove the space and save the file again) the compat.browser file.
April 9th, 2012 at 8:14 am
I have followed the blog and created a adaptor for content editor web part.
Content Editor web parts are now appearing in the mobile view.
But they appear in bottom of the page, i have added the web part on top of the page. Is there any issues or any idea why it is happening like this?
April 11th, 2012 at 11:37 am
[...] http://blog.mastykarz.nl/inconvenient-content-editor-web-part/ [...]
April 18th, 2012 at 5:13 pm
@Shob_p: Could it have something to do with your CSS or are the Web Parts rendered in a whole different place on the page?
May 2nd, 2012 at 1:54 pm
The solution that you provided is 100% working for Content Editor Webpart. Thanks.
Is there a solution as well for columns with type HTML editor?
May 4th, 2012 at 10:16 am
@Adrian: you would need to create a similar Control Adapter for the control that you are using to display the value of the Rich HTML Field.