10/01/2008
This may be a minor problem but it is something that I think could useful for those of us with internet-facing sites.
In using an SEO Analysis Tool (Bruce Clay's Keyword Density Analyzer), I discovered that my keywords were skewed due to the repeated use of the phrses "scroll up" and "scroll down".
After some research, I found that this is due to the ASPMenu appending the scroll arrows to the top and bottom of each dropdown menu in case the total height of the menu is greater than the height of the browser. The ALT tags for these arrows have "Scroll Up" and "Scroll Down" values. While this is nice for making the site more user friendly, it makes the images I care about rank further down than the scroll images (the scroll images' ALT tags rank top since they are displayed so often). This is not good.
So, how does one fix this? Well, open your MasterPage and find the menu (ASPMenu or MossMenu) and add the following two lines to the properties of the menu tag:
ScrollUpText="" ScrollDownText=""
This makes the ALT tag "up" and "down" and not a phrase. (The "Up" and "Down" are in the core.js or menu.js file in the 12 hive, but we don't want to change that, now, do we?)
For those of you who think this may hurt the handicap accessibility of your site, I offer only that I have not been able to hover over these images long enough to even see the ALT text pop up. 09/19/2008
I was recently asked about adding a "Log out" button to the Site Actions menu. As luck would have it, I had written a feature on it a good while back. It's not all that complicated, but I figure that it can't hurt to share in case anyone out there wanted it and (most importantly) wanted it ready made.
Here's what you get:
Feature.xml: Nothing really special here except for the Description. If you want it as something differnet, then feel free to change it.
<?xml version="1.0" encoding="utf-8" ?> <Feature Id="AA929AFF-4602-4d7f-A501-B80AC9A4BB52" Title="Site Actions Logout" Description="Adds a logout button to the Site Actions Menu" Scope="Site" xmlns=" http://schemas.microsoft.com/sharepoint/"> <ElementManifests> <ElementManifest Location="elements.xml" /> </ElementManifests> </Feature>
Elements.xml: Here is there the details of the feature are set. The GroupId puts the item on the Site Actions menu. The Sequence makes it the bottom-most (well, the 2000th) item. If you need it moved, play with this value. RequireSiteAdministrator is important in that this means the item will only show up for Site Admins. You may want to play with this. But if you remove it, it will appear for everyone. So for those of you with Anonymous Access setup, your Site Actions menu will appear for your anonymous users - but with only this item showing. Finally, the UrlAction. This is the link that's created. I have included the SharePoint modified not to close the browser after loggin out. Copy this file to the LAYOUTS folder if you'd prefer it.
<?xml version="1.0" encoding="utf-8" ?> <Elements xmlns=" http://schemas.microsoft.com/sharepoint/"> <CustomAction Id="SignOutPage1" GroupId="SiteActions" Location="Microsoft.SharePoint.StandardMenu" Sequence="2000" Title="Sign Out" Rights="ManageWeb" RequireSiteAdministrator="True" Description="Logout of this site" > <UrlAction Url="~site/_layouts/signout.aspx"/> </CustomAction> </Elements>
Signout.aspx: This is the Microsoft signout.aspx page with the window.close() command commented out. This logs you out, but doesn't close the browser. 09/03/2008
In my post about the 301 vs 302 redirects in SharePoint, I mentioned that if anyone requested the "Hop Tester" I wrote to test if the redirects are 301's or 302's that I'd post it in my downloads section. Well, it's been requested, so here it is.
The entire solution is in the ZIP file (it is compiled in the BIN/Release directory if you just want the EXE). I am including the code in case you want to modify it for your own use. What's provided is fairly bare-bones and isn't pretty. I wrote it for pure functionality, so development stopped once it started working. If you want to take it and modofy it and make it all purdy, go for it.
Typical disclaimer. Use at your own risk, CYA, CmyA, etc.
08/25/2008
The Variations Editor - a Free Application to Scan, Diagnose, and Edit troubled SharePoint Variations sites.
As readers of my blog have probably noticed, I spend alot of my time in SharePoint trying to work with Variations. You probably also noticed that I've spent alot of time trying to fix Variations' problems - espically in the Relationships List. This is not always easy. As it turns out, Variations is not the most stable of features in SharePoint. So, in an effort to help make life easier, I started writing an application that would analyze existing Variations sites, make note of potential errors, and give me the opportunity to fix these problems one at a time. Thus the Variations Editor was born.
UPDATES BELOW
Yes, I know there are other solutions out there to "fix" variations. Custom STSADM commands have been released that automatically fix some problems. I have tried these and they didn't help fix my problems. Also, being a picky admin, I didn't like the idea that things were being fixed without my knowledge. I like to see what all is being changed and, if I so choose, NOT make some changes.
The application has been completed and is now available for download from my Downloads site. This application is offered free of charge. And, as with most software, use this at your own risk. I like to think that a fair trade is to offer my software for free in exchange for you not suing me for any reason. That being said, the software is free. Don't sue me.
Before I get into the details of the applicaiton, here is a screen shot. (Click for a larger view.)
What you see is the main screen of the Variations Editor. Some features of the Variations Editor include:
- Automatically scanning the local farm for Variations-enabled site collections.
- Security Trimmed site list.
- Correcting corrupt/missing Root Nodes in the Relationships List
- Highlighting sites/pages that contain errors.
- Variation error correction granularity down to the individual-error level.
- A full report of all sites/pages containing errors and warnings.
- Display the status of the Variations Timer Job
- The ability to delete potentially flawed variation labels.
- ...and more.
Using one of the worst scenarios of Variations (restored from backup from a solution that was moved via Deployment Job), I was able to discover and correct flaws that allowed for a once stalled variations propigation to be able to continue. I would also like to thank Jamie McAllister for helping me test this applicaiton. Visit his blog at: http://the-north.com/sharepoint/
I welcome you to download and use this application if you are having trouble with SharePoint Variations. This is a full-featured release (no "pro" version to buy later). It's even free for consultant firms who may need a tool diagnosing and fixing clients' Variations sites.
If you do use it, I welcome comments and am looking to see what the general reaction to this application is. I believe this could be a valuable tool for SharePoint admins who have to deal with the fragility of SharePoint Variations and would love to hear from you as you use the program both to see if it suits your needs as well as to get feedback in order to make (a hopeful version 2) an even better product.
If you've had to deal with Variations problems and have struggled with correcting them, please let me know if this would be something worth having.
UPDATE (9-9-8): I have posted a beta version of the app that has a more robust reoprting page. This version has links on the reporting page that will allow you to go from the reporting page to the diagnostics page without having to find the site/page in the tree view. It also has pretty icons that give a more "at a glance" view of the errors/warning found.
UPDATE (9-11-8): Code Fix alert! Feedback is a good thing. It makes applications better. One comment on the Variations Editor mentioned that it did not work for site collections created with a non-English Language. This turns out to be a problem because Microsoft, in their infinate wisdom, decided that the title of a HIDDEN list should be translated. Thus, what is "Relationships List" in English-based sites is, for example, "Elenco relazioni" in Italian-based sites and whatever else it is translated to in other languages. So accessing this list via the standard SPList list = web.lists["Relationships List"]; doesn't work. Thankfully the workaround isn't awful, but still, I can't say I understand why such an important list, espicially one that is HIDDEN needs to have it's name (but not URL) translated. Unreal. Anyway, for those users out there who have non-English site collections, please use the VariationsEditor1.1b.zip file for your sites. This has the code fix in it to look for Relationships Lists by URL and not by name.
UPDATE (9-23-8): Reporting Enhancement. At the suggestion of a user (thanks Eric), I have added the ability to export the Summary Report as an XML file. I chose XML for its simplicity, versitility, and because I haven't done much with exporting Excel Files. But XML should satisfy basic reporting needs until Version 2.0 is completed. This new feature is in the VariationsEditor1.1c.zip file. It is in the Downloads section with the rest of the versions.
UPDATE (10-9-8): Manually Adding Missing GroupID. A new feature has been added to the Variations Editor, one that is truly a beta feature. Until now, the ability to edit the GroupID for the site items was not possible. This was due to the fact that everything hinged on this value. Well, this feature was needed, so I have added it to the application. It is a bit rough, however, in that it requires you to manually enter the missing GroupID. I have explained the process as well as a warning in the Users Manual attached with the application (in the ZIP). While the feature works, it is very rough. I preferred to get the feature added so that it will help those who need it instead of waiting for v2.0 to be finished. Please read the manual to understand the limitations of this new feature. If you have any questions about what value to put in the GroupID, please contact me. I promise v2.0 will have this as a much more elegantly designed feautre. The new version is in the VariationsEditor1.1d.zip file. It is in the Downloads section with the rest of the versions. 07/23/2008
The Announcements list is a default item in Team Sites. The webparts that are generated with them are nice to have out of the box, but they have one limitation that has always bothered me – they are only at a site level. In order to get Global Announcements, you’d have to do one of two things: create an Event on the Announcements lists and have them propagate to all their sub lists, or write a webpart that gets all the Announcements Lists. Me, I did the latter.
My goal was to build a webpart that would look up the site hierarchy and get all the entries from the Announcements lists from all the site’s parents. This will create a list that will show only the relevant Announcements since sister sites should not relate to the current site, but parent sites will. For example, imagine a root site that has an announcements list meant for the entire company. Below the root sire are the HR and Accounting sites. They too have announcements, but they only post announcements for their depts. Below Accounting are the Billing and Accounts Payable departments. They too have local announcements. By adding the Global Announcements webpart to the Billing webpage, users of the site will see Announcements from Billing, Accounting, and the Root site. Since Announcements from Accounts Payable and HR do not directly apply to Billing (and are not in the direct path from Billing to the root), they are removed from the global list.
How it works.
The webpart makes one assumption: that the Announcements list is the out of the box Announcements List – unchanged in any way. If you want to adjust for differences, I’ve included the code in the download.
One key problem from just iterating through the site hierarchy was sorting the announcements so they were in proper order. Not wanting to sort them manually, I turned to the SPSiteDataQuery. This allows for a CAML query to be placed over an entire site collection or, as how I used it, a specific number of lists. To do this, the SPSiteDataQuery is divided up into four section: the Lists, the CAML, the Web Scope, and the ViewFields.
The Lists is fairly straightforward. It begins (and ends) with a <Lists> (</Lists>) tag. Here is where you’ll place the specific lists to query. You can also have it search all the lists in the SiteCollection by leaving it blank. But in this example, we’ll specify lists. To do this, you need to get the ID for the lists and place them in List tags. The item will look like this:
<List ID=”LIST-GUID-GOES-HERE” />
From there, we fill the Query. This is straightforward CAML to give selection criteria for the lists. I have it to filter out entries that have expired. I won’t go oever the CAML since the query is in the code and teaching CAML isn’t in the scope of this discussion.
Finally, the ViewFields need to be addressed. Much like the SELECT command in a SQL query, this will choose the fields to make available for use/display. Here a series of <FieldRef Name=”Title” /> tags (replacing “Title” with the field name you want displayed) tell the query what to return.
One nice addition to this query is the RowLimit property. You can tell the query how many items to return. This is helpful in order to limit the number of items displayed. I’d rather let SharePoint do my work for me than write code to decide how many records have been returned.
From here, you call the GetSiteData(query) function in the SPContext.Current.Web object to get a DataTable of the items you requested. For this code, it’s the top few announcements from the sites above the current site.
Some Problems
Of course, getting list items in Anonymous sites can cause a problem. So it will need special security file (CAS) for non-authenticated sites. Also, if you don’t have access to a site, the CatchAccessDeniedException setting is set to false when accessing the site. This and a try/catch will let the code skip any Announcements that the user doesn’t have permission to view (or for those sites where the Announcements list has been removed.
Additions
The OOtB Announcements part offers up the Author in addition to the announcement body and the title. I have included those and added another item. Now, each announcement will show what site it originated at. This will help the user understand what context the announcement was made in. This feature (as well as the Author display) can be turned off in the WebPart Settings.
One deletion is the “Add New Announcement” link. I will add this later. Part of the problem with this link was, to me, where does one put it. And since my initial scope of the webpart was to display announcement and not add them, I left it at a display only. I’ll let you know when I add this feature in.
The Code
Enjoy it. I put the code out there in case you wanted to make adjustments to it. It’s in my downloads section. If you use it, I hope it suits your needs. If you change it, please leave my name in it. I like credit. Credit is nice. But the usual disclaimers apply. Use at your own risk. And this is another reason why I am including the code. I like knowing what’s on my farm. I think you should have the ability to know as well. This way, you can see for yourself by seeing the code.
One more thing. If you make any improvements/changes, please let me know. I would love to see how the webpart has been made better. The last time I gave code out, another user on the site (thanks Chris) improved my code and made it easier for people to use.
Enjoy. I know it's not much, but I hope you find it somewhat useful. 06/27/2008
Updated 7-1-8.
Updated 9-3-8
I have been trying to figure out how to change SharePoint's default 302 redirect to a 301 redirect for a coupld of weeks now in order to help my site's search-friendliness. For those of you that don't know, SharePoint handles all it's redirects with 302 redirects. These are not liked by search engines. So while SharePoint's search doesn't have a problem with this, Google's does, so this is a problem that I need to address.
There is help online, but I have to admit that I had some trouble with the code provided. Thankfully, I've been able to modify the code online in order to get it working for a more general use.
First off, let me say that the basis for this code is not mine. I found it at:
Here Mr. Mastykarz does a good job solving this problem for his environment. What I am presenting here is a modified version of his code that doesn't have all of the items that are either specific to his environment or hardcoded into the code. That being said, I am not going to explain the code as Waldek Mastykarz did a very good job explaining what the code does in his blog post and I don't want to steal all the credit from Mr. Mastykarz.
The code presented is a C# Class file that you'll need to create/compile just like the original. What I will do is present my changes and final code listing for what I believe make this solution more suable for a generic environment.
Now, since I am presenting a new version of someone else's code, what I will do is explain my changes.
First and foremost, I removed his handling for Variations as I feel his method is not a good one for general use since he used a (hard coded) non-standard language label ("nl") and hardcoded a couple other items into the redirect paths that do not apply to every SharePoint installation. That being said, the entirety of his Variation-handling code has been removed. This is instead handled in by modifying the VariationRootLanding.ascx file. This will be expanded upon below.
Second, I took out an amendment he added to his code to handle Infopath and Sharepoint Designer (which registers as Frontpage, oddly). I could not replicate the problem this was added to solve and, in fact, it being there caused an error when I tried to use the code, so it was removed.
After making these changes I compliled the class and placed it in the BIN directory of site site. Note, this did not work when I placed the control in the GAC. So if you have multiple sites in your farm, you're going to have multiple copies of this control.
After the control was installed, one other change was made that involved the use of Elevated Privlidges in the code. This is a problem that needed to be addressed as the original code will not run correctly otherwise.
For my situation, and most people's situation I would think, the use of Elevated Permissions is not allowed in Medium (or lower) trust levels. Since I am placing this on an internet-facing, anonymous site, it definately didn't work for me. That being said, I had to create a Custom CAS entry to allow this to run in my site's trust level. For how to do this, see my previous blog post.
In addition to creating a custom CAS entry, you also have to edit your web.config file to tell your site to use this method for redirects. To do this, edit your site's web.config and scroll down until you find the httpModules section. Just after the <clear /> tag, add in the following:
<add name="CustomRedirectModule" type="Custom.Sharepoint.RedirectFix.RedirectModule" />
Note, this has to be the first on after the clear to make sure it overrides any other redirct methods in other httpModules.
Save the web.config and you're now using this module to handle your redirects. I had to write a quick application to test the redirect hops to insure the 301's were being used and not the 302's. If you want this, let me know and I'll post it in my downloads section.
UPDATE: 9-3-8. I posted the Hop Tester.
Now the control's code:
using System; using System.Collections.Generic; using System.Text; using System.Web; using System.Text.RegularExpressions; using Microsoft.SharePoint; using Microsoft.SharePoint.Publishing;
namespace Custom.Sharepoint.RedirectFix { public class RedirectModule : IHttpModule { #region IHttpModule Members public void Dispose() { } public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_BeginRequest); }
void context_BeginRequest(object sender, EventArgs e) { HttpApplication app = (HttpApplication)sender;
string userAgent = app.Request.UserAgent.ToLowerInvariant(); if (userAgent.Contains("infopath") || userAgent.Contains("frontpage")) return; string requestUrl = app.Request.Url.ToString(); Regex regEx = new Regex(@"^https?://.*(?<itemUrl>/[^/]+\.[^/\.]+)$"); if (regEx.IsMatch(requestUrl)) return; if (!requestUrl.EndsWith("/", StringComparison.CurrentCulture)) requestUrl += "/"; string destinationUrl = String.Empty; SPSecurity.RunWithElevatedPrivileges(delegate() { try { using (SPSite site = new SPSite(requestUrl)) { using (SPWeb web = site.OpenWeb()) { if (PublishingWeb.IsPublishingWeb(web)) { PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web); destinationUrl = String.Concat(requestUrl, publishingWeb.DefaultPage.Url); } else { destinationUrl = String.Concat(requestUrl, "index.aspx"); destinationUrl = String.Concat(requestUrl, web.RootFolder.WelcomePage.ToString().Substring(web.RootFolder.WelcomePage.ToString().LastIndexOf('.') + 1)); } } } } catch { } }); if (!String.IsNullOrEmpty(destinationUrl)) { app.Response.AddHeader("Location", destinationUrl); app.Response.StatusCode = 301; } } #endregion
}//class }//namespace
Now, if you don't use variations, you're done. However, if you do have a site that is variation enabled, to handle the variations aspect, you will need to modify the VariationRootLogic.ascx file.
This file is found in the 12 Hive's TEMPLATE\CONTROLTEMPLATES folder. This file is easily editable in Visual Studio. To edit it, open the ASCX file and find the OnLoad function. It will look like this:
protected override void OnLoad(EventArgs e) { base.OnLoad(e); string targetUrl = this.GetRedirectTargetUrl(); if (!string.IsNullOrEmpty(targetUrl)) { SPUtility.Redirect(targetUrl, SPRedirectFlags.Default, Context); } }
Comment out (or just remove) the SPUtility line and replace it with the following:
Context.Response.Status = "301 Moved Permanently"; Context.Response.AddHeader("Location",targetUrl);
making the final funtion look like:
protected override void OnLoad(EventArgs e) { base.OnLoad(e); string targetUrl = this.GetRedirectTargetUrl(); if (!string.IsNullOrEmpty(targetUrl)) { //SPUtility.Redirect(targetUrl, SPRedirectFlags.Default, Context); Context.Response.Status = "301 Moved Permanently"; Context.Response.AddHeader("Location",targetUrl); } }
That's it. Save this file and you're good to go. I hope this helps and thank you to Waldek Mastykarz for getting me started on this.
UPDATE (7-1-8):
Apparently it took a while to notice this, but I needed to put back some code that I took out of the original code. In the code above, there is now a highlighted (purple and italics) section that allows for InfoPath and SharePoint Designer to connect properly. Apaprently, the VM Sandbox didn't un-cache itself until last night and this piece of code that caused me trouble turned out to be needed. Apaprently, if SPD finds that you've 301'd your site, it think it has been moved permantly and won't let you connect. So this is needed.
For those of you writing your own redirect hop tester, make sure you set your HttpWebRequest.UserAgent to something as a NULL (default) value will cause an error. 06/24/2008
If you've coded a webpart, odds are that you've run into the following message at least once:
Request for the permission of type 'Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' failed.
Not fun. What this means is that your webpart has violated the current security policy and is trying to access something that SharePoint says its not supposed to access. This is very common in internet-facing sites that use Anonymous Access.
For exmaple, here is what I recently had to do. I am writing a custom search webpart to search a list. This is great if you're authenticated. But on an anonymous-enabled site, I have no rights to the list (unless you remove LockDownMode, but we're not talking about that right now).
So, since I have no rights on the site as an anonymous user, when I try to search it, I get the error message above. So my webpart was DOA. I needed a solution. Microsoft has three possible scenarios to fix this solution:
- Run your site in Full Trust.
- Put the webpart in the GAC.
- Create your own Custom Code Access Security Policy.
The fisrt two, as you may or may not know, are not very good options for security reasons. And me, personally, I don't like using the GAC. So that leaves option 3.
So, since this was not the easiest thing for me to figure out (many websites out there, but none seemed to do the trick for what I really needed) I decided to put it out there in case my way of explaining it makes more sense than the other ways out on the internets.
Let me say that there is a way to automate this by deploying the webpart in a custom solution. It will make the changes to the web.config and make the security policy file for you. This is great, but I a) don't always use solutions and b) don't really want many custom config files everytime i do this and c) am too big a control freak to just "let it go in without me". So here's how to create a custom security policy for a specific webpart dll.
First, goto the CONFIG folder in your 12 Hive. There you will see the two standard security config files:
wss_mediumtrust.config and wss_minimaltrust.config.
Depending on the trust level you're running currently (I use Medium, so my example will be based on Medium Trust), make a copy of the file you're currently using and name it something meanginful (e.g. wss_InternetFacingTrust.config). This will be your new trust file. Go ahead and open it up for editing (Visual Studio is nice here).
In this file, we're going to add two sections.
First, locate the NamedPermissionSets section. At the bottom of this section, add the following:
<PermissionSet class="NamedPermissionSet" version="1" Description="Permission set for my control" Name="MyCustomPermissionSet"> <IPermission class="AspNetHostingPermission" version="1" Level="Unrestricted" /> <IPermission class="SecurityPermission" version="1" Flags="Execution,ControlThread,UnmanagedCode,ControlPrincipal" /> <IPermission class="System.Security.Permissions.EnvironmentPermission" version="1" Unrestricted="true" /> <IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" ObjectModel="True" Impersonate="True" UnsafeSaveOnGet="True" /> <IPermission class="System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Unrestricted="true" /> </PermissionSet>
Yeah, I stole this. I forget where, but in looking, everyone has the same PermissionSet for this. So I will repeat it here. If you were the very first one to put this together, let me know and I'll credit you.
What this does is set up a set of permissions that we can reference later in this file. Note the Name section. This is how we're going to reference this peticular policy (by using "MyCustomPermissionSet" in this case).
Next, we'll use this new PermissionSet. In the config file, find the CodeGroup tags. There may be a few of them. The first one will be something like:
<CodeGroup class="FirstMatchCodeGroup" ... />. Below it are other CodeGroups. We are going to add a new CodeGroup in this section for our assembly. So copy the following code:
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="MyCustomPermissionSet"> <IMembershipCondition version="1" Name="The.Webpart.assembly.name.goes.here" class="StrongNameMembershipCondition" PublicKeyBlob="A REALLY LONG NUMBER GOES HERE" AssemblyVersion="1.0.0.0" /> </CodeGroup>
Paste this below the FirstMatchCodeGroup CodeGroup. This is important that you paste it after the "FirstMatchCodeGroup" since all of the other CodeGroups are "UnionCodeGroups". This is worth noting because depending on the type of UnionCodeGroup, its criteria may be broad enough to encompass your new assembly and once it is accepted by a CodeGroup it stops looking. So if you put your new CodeGroup last, odds are that your changes will never be seen. So, make sure it's the first CodeGroup.
Things to note:
First, the PermissionSetName should match the Name field from the PermissionSet.
Second, note the Name field. This is the assembly name for your dll. This is the same assembly name found in the SafeControls section of your web.config. Copy and paste that over "The.Webpart.assembly.name.goes.here" that I have above.
Third, note the PublicKeyBlob section. This will need to be discovered from your dll. To find this, the only way I have found this far is by using a program called "ildasm.exe". It comes with the .Net SDK. My path was "C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin" but there is no guarntee we put them in the same place. Search your computer for this file. Run it and drag your dll into the main screen. Double click the "M A N I F E S T" line. An ugly yellow screen will popup. Scroll down until you see ".publickey". It'll be ugly. Copy everything in that section and paste it into NotePad. When you do, remove everything after the "//"s (it'll copy as several lines). Then remove everything that's not a number. Then remove the spaces. Then make it all one big line. Copy that and paste it into the CodeGroup replacing what I have above as "A REALLY LONG NUMBER GOES HERE".
I know. That wasn't fun. But this is SharePoint and nothing interesting in SharePoint is all fun.
But for refernece, the section you're looking for will look something like this:
.publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00 // .$.............. 00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00 // .$..RSA1........ AF 77 24 29 C2 8A E7 6D 11 1E 9F 66 2C 2A 9C DD // .w$)...m...f,*.. F0 19 10 D8 3E A1 5F 07 79 8B 36 0F 2E 96 C3 35 // ....>._.y.6....5 12 61 B8 B0 F0 85 8B C8 B2 84 B7 89 05 45 C9 45 // .a...........E.E 36 6D B1 DC C2 3F E7 0C 0C 75 05 FD 4D EE 48 DA // 6m...?...u..M.H. 74 1B 2E 60 A1 2B 55 60 AB A6 7B A3 4B F0 93 D7 // t..`.+U`..{.K... ED 02 52 22 9C CE D8 0A 82 5F AC 64 9A B0 50 9A // ..R"....._.d..P. 93 C2 47 DE C5 CC 97 C4 B3 4E 2B 54 68 5C CE E0 // ..G......N+Th\.. 6D 1B 37 E5 F6 30 F5 13 FB 10 1C EF 8E 79 D1 D3 ) // m.7..0.......y..
Ok. Save your config file cause we're done with it.
Now, goto the web.config file for your site. Find the securityPolicy section. Add in the following line below the ones listed for WSS_Medium and WSS_Minimal:
<trustLevel name="WSS_dotCOM" policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_InternetFacingTrust.config" />
Of course, change this line to reflect the config file you just created and, if you want, change "WSS_dotCOM" to something else if you want it named differently.
Next, find the
<trust level="WSS_Medium" originUrl="" />
line. Change this to:
<trust level="WSS_dotCOM" originUrl="" />
Save the web.config and refresh your page. The control (well, if you placed your dll in the BIN) should now have the correct permissions. 05/01/2008
Love it or hate it, JavaScript is a necessity in SharePoint in many occasions. My task today, in fact, was to add the Google JavaScript Tracking Code to several banner ads on my site. Not a very straight-foward task in SharePoint. Nor is adding any JavaScript to a page in SharePoint. But I found a way to do just that.
To set the stage, the banner ads are added to the site via HTML in the Page Content fields of the page (as is most content on Publishing Pages). (Before you ask, these ads were placed such that I couldn't add a Content Editor Web Part to the page in the correct place without creating another Page Layout). And as we all know, Microsoft decided that they know us better than we know ourselves and protected us from adding JavaScript to HTML in the Page Content sections by removing the JavaScript from the HTML when you save the page.
Thank you Microsoft. I feel safe from my own malicious ways now.
So how does one add, say, an onClick event to an HTML tag in the Page Content section? Well, it's not as bad as you might think.
First, let's take a look at the Google Tracking Code. What Google wants is the following added to any banner Anchor tags:
onClick="javascript: pageTracker._trackPageview('/bannerads/bannerSponsor/BannerLocation');"
To start the process, I first edited the Page Content HTML to have the banner's Anchor tags have an ID field. So I added ID="BANNER1" to the Anchor Tag and saved the HTML.
Next, in a web part zone near the bottom of the page (loading after the Page Content Area to be sure the JavaScript can see the correct object), I added a Content Editor Web Part. I used a CEWP since Microsoft apparently finds these areas for HTML input safe for JavaScript to play in. To avoid it being seen, I made the CEWP a hidden webpart. In it I added the following to the CEWP's Source Editor:
<script> var bannerAd = document.getElementById('BANNER1'); bannerAd.onclick = function() {pageTracker._trackPageview('/bannerads/bannerSponsor/BannerLocation');}; </script>
By adding the onclick function via code, this web part can tell the Page Content tags to have an onClick event without having the JavaScript part of the Page Content's HTML.
I hope this helps you un-save yourself from Microsoft's valiant attempts to save yourself from adding useful JavaScript to your pages. 04/22/2008
I don't know how many of you have played with the MOSSMenu that Microsoft released to fix the AspMenu issue with having your mouse over the menu when the page loads causing a rather ugly error. But for those of you looking to use the MOSSMenu but don't want to build the dll yourself, I have gotten one working and have uploaded it to my downloads site.
Here's what to do:
- Take the Microsoft.SDK.SharePointServer.Samples.dll and put it in the GAC.
- Edit the web.config file and add in the following SafeControls entry: <SafeControl Assembly="Microsoft.SDK.SharePointServer.Samples, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6f07a0c27c74cfa1" Namespace="Microsoft.SDK.SharePointServer.Samples" TypeName="*" Safe="True" AllowRemoteDesigner="True"/>
- Copy the MossMenu.js file to \12\TEMPLATE\LAYOUTS
- Edit your MasterPage with the following: <%@ Register Assembly="Microsoft.SDK.SharePointServer.Samples, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6f07a0c27c74cfa1" Namespace="Microsoft.SDK.SharePointServer.Samples" TagPrefix="Sharepoint" %>
- Change the SharePoint:AspMenu tag with SharePoint:MossMenu. Leave all the config tags the same.
That's it. I have included the DLL, the JS file, and a txt file with the above entries in the MossMenuBuilt.zip file in my downloads area (located at: http://www.thesug.org/blogs/lsuslinky/Downloads/Forms/AllItems.aspx )
Typical CYA disclaimer, but it is Microsoft's code and it worked on my sandbox.
I hope this helps.
UPDATE: Apparently, if you have a REALLY, REALLY slow internet connection (as one of my users does) and can click a menu option and (before the page loads) click another menu option, you'll get the Operation Aborted error still. For the life of me, I cannot re-create this error. I have pushed this to my production boxes and it works fine for me. But for those on a REAAAAAAAAAAAAAALY slow connection, this may still be a problem. How does one fix this situation? I have no clue.
| |