Monday, December 31, 2007

SCDNUG 2007 Retrospective

2007 was a great year for the Space Coast Dot Net User Group (SCDNUG.org). Ken Tucker the leader of the group and Microsoft MVP was able to invite all kinds of speakers starting from Scott Guthrie to local speakers, such as Christian Loris, Walt Williams and myself. Ken worked to improve the image and the message of the group and at the end of the year we even started our own book review program. Looking at the events this year I am amazed at the learning and network opportunities the group provided. And all of this at NO COST, FREE! Have a look at the speakers and judge for your self:

January - Ken Tucker - Community Launch Part 1

February - Mikhail Dikov - Community Launch Part 2

March - Scott Guthrie

April - Walter Williams - OOP

May - David McNamee - Windows Workflow

June - VB Team - What’s new in VB9

July - Brian Noyes - Connecting Apps with WCF

Aug - Christian Loris - Validation Application blocks

September - Jeff N Joe Road Show - Silverlight

September - Cory Foy - Ruby for C# developers

October - Russ Fustino - Tool Shed Tour

October - Mike Culver - Amazon Web services for the .net developers

Novemver - Ken Tucker - Intro to Linq

December - Joe Heally - Visual Studio 2008 Install Fest

We still need to be more proactive in popularizing the purpose and the value of our group to IT Pros and developers. I hope in 2008 we'll be able to follow the steps of other groups and do better job in distributing flyers in key locations in the Melbourne/Palm Bay/Cocoa area, and utilizing community resources, such as public radio stations and community colleges. We already started by creating a map on live.com and improving our home page, but there is still a lot of potential and I hope in 2008 we will be able to bring the group to a new level.

Interested to learn more about SCDNUG check out our web site http://scdnug.org/.

Dovizhdane!

Thursday, December 13, 2007

Comprehensive guide for MS Office and SharePoint integration developers

The book Pro SharePoint solution Development, Combining .Net, SharePoint, and Office 2007 written by Microsoft insiders Ed Hill, Susie Adams is an indebt review of how to utilize SharePoint in the Microsoft Office ecosystem. This book from the Pro series of Apress delivers a variety of advanced examples, richly illustrated with sample code, downloadable from Apress, and step by step instructions and illustrations in the book itself.

The organization of the book is very convenient and the first four chapters allow the reader to brush up his knowledge about MS Offices and SharePoint with abundant external links. Each consecutive chapter after that represents a standalone example based on a simplified real-world scenario. The examples are focused on the integration with a particular MS Office product. For example Chapter 5 demonstrates a scenario where MS Word integrates with SharePoint and Chapter 9 shows how to construct PowerPoint slides using content stored in a SharePoint list. Every example starts with an introduction and walkthrough, which allows the reader to start reading the chapter directly without losing context.

The complexity of integrating products of the MS Office family in enterprise solutions requires quite a bit of knowledge and experience thus I do not recommend this book to beginners in SharePoint and MS Office programming. While this book has a plenty of introductory and historical information about MS Office development and SharePoint customization, it does not emphasize on important steps of professional SharePoint development such as creation of SharePoint solutions, list and site template customization and provisioning. However if you are already familiar with SharePoint (WSS 3, MOSS 2007) concepts such as solutions, features, workflow etc., this is the book to put all these features in the context of enterprise applications. Since I started working on an integration project with MS Office and SharePoint at the time I was reading the book, I took away plenty of ideas to use in my project.

The software and hardware requirements for the examples in this book are quite high, so if you want to be able to implement them on your own you need to allocate some time to prepare a system with MOSS 2007, MS Office 2007 Enterprise, VS 2008 Professional or Team Edition and for the first example MS Office 2003. In addition there are several manual actions, which require a bit more time. Something, which may not be obvious from the title, is the heavy use of the new MS Office document standard - Office Open XML (commonly referred to as OOXML or OpenXML). This was my first exposure to this format specification and I found its use throughout the book very useful.

Overall this book is of great value to intermediate and advanced developers, working on enterprise applications based on the MS Office system or integration projects with third party vendors. The examples can be read independently and each one of them not only demonstrates the implementation of a particular scenario, but also provokes ideas for other projects.

Dovizhdane!

1590598083, 978-1590598085

Tuesday, November 20, 2007

Support multiple scopes in SPEventReceiver class

Quite often when I create a feature SPEventReceiver I am not certain what would be the best scope to use it. In other situations I am copying existing code from a feature scoped differently than the newly created one. After couple of these you get tired of trying to find out what is the actual meaning of the properties parameter, as it changes with the scope change.

So here is a little snippet that I started using to save some time and effort. In this particular case I am fetching the current web application from the feature properties:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWebApplication app = null;

if (properties.Feature.Parent is SPSite)

{

SPSite siteCollection = properties.Feature.Parent as SPSite;

app = siteCollection.WebApplication;

}

else if (properties.Feature.Parent is SPWeb)

{

SPWeb web = properties.Feature.Parent as SPWeb;

app = web.Site.WebApplication;

}

else if (properties.Feature.Parent is SPWebApplication)

{

app = properties.Feature.Parent as SPWebApplication;

}

else if (properties.Feature.Parent is SPFarm)

{

throw new Exception("Not supported as farm feature.");

}

}

This code can be used in some of my previous posts:

SharePoint Resources, Types, Use and Deployment (Update)

SharePoint Resources, Types, Use and Deployment

Dovizhdane!

Wednesday, November 14, 2007

November SCDNUG Meeting, Great Event

Tonight's meeting of the Space Coast Dot Net User Group showed what user groups are all about. Ken Tucker (MVP) presented Introduction in Linq. The informal atmosphere and the fact that most of the attendees already knew each other, enabled a great dialog and discussion. We also kicked off our book review program and Walt Williams volunteered to write a review about Pro WPF: Windows Presentation Foundation in .NET 3.0. I hope in addition to his review, he'll find time to share some of the content and the examples in the book with the group. This is just another great opportunity to learn the latest technologies and contribute to the community.

Dovizhdane!

Thursday, November 01, 2007

Using ASP.NET AJAX extensions in SharePoint WebParts

As I mentioned in my previous post I a while ago I started working on a project with AJAX enabled WebParts. I already have been playing with AJAX and also working with SharePoint and WebParts in my previous projects at G360 and in the .Net community. Nevertheless I did not get a chance to work with both technologies in one project, so there you go, all my wishes came true.

With the release of ASP.NET AJAX and the expected support in SharePoint SP1 it makes good sense to continue using this technology instead of other alternatives such as AJAX.NET. One of the biggest advantages is that ASP.NET developers have the choice to use UpdatePanel and the control toolkit to upgrade existing applications or develop new one without a major learning curve requirements. The UpdatePanel control encapsulates a lot of functionality and allows developers to continue to use the ASP.NET controls and programming style, but overrides the post-back events with an asynchronous call and partial update of the area covered by the UpdatePanel. Developers also have the option to go into more sophisticated AJAX development techniques using directly the client and server side AJAX libraries. With coming support for JavaScript Intellisense and debugging in Visual Studio 2008, this option will be increasingly more attractive, but in Visual Studio 2005 these luxuries are not available.

When it comes to using ASP.NET AJAX in SharePoint nothing is written in stone, but one big chunk of the mystery is solved in this post from Mike Ammerlaan - http://sharepoint.microsoft.com/blogs/mike/Lists/Posts/Post.aspx?ID=3. In his post Mike describes the steps, but there is still some work to make this function properly in a solution that can be deployed to a customer. One of the issues is how to make the web.config changes using SharePoint Feature. The solution comes from the SharePoint 2007 Features project on CodePlex, which contains a feature that does exactly that. Another issue is that to add the script manager we don't really want to edit to the master pages. Even though some don't recommend this technique, I found that adding the ScriptManager dynamically worked well for my project and greatly simplified the deployment. This is the code I used:

protected override void OnInit(EventArgs e)
{
base.OnInit(e);

// Let's find if the ScriptManager exists and add it if not
scriptManager = ScriptManager.GetCurrent(Page);
if (scriptManager == null)
{
scriptManager = new ScriptManager();
if (Page.Form != null)
{
// Insert script manager after the web part manager
for (int controlIndex = 0; controlIndex < Page.Form.Controls.Count; controlIndex++)
{
if (Page.Form.Controls[controlIndex].GetType() == WebPartManager.GetType())
{
Page.Form.Controls.AddAt(controlIndex + 1, scriptManager);
}
}
}
}
}

Using ASP.NET AJAX Control Toolkit was also very straightforward. Most of the controls worked properly in SharePoint. I did not have the chance to test all of them, but it looks like controls that iterate many objects on the page and make style modifications to many controls work somewhat slower, if at all, in the default SharePoint page. The validation extender, for example, sometimes does not position well the call out next to the field, or the modal pop-up mocks up the whole page and causes high CPU utilization. Nevertheless there are plenty controls that work well. One of the controls I use frequently is the tabbed control, which is very handy for configuration pages.

One thing I found cumbersome is to use UpdatePanel and some of the other AJAX enabled template controls directly from server side code. I know a lot of web control and WebPart developers have long forgotten the design-time environment of the web forms, but would it be nice to be able to use a visual tool to design WebParts and to be able to easily test them? I hope I'll find some time to write about the solution I worked out for my projects. Until then ...

Dovizhdane!

Thursday, October 11, 2007

MOSSMOSIS Orlando

Recently Scott Schwarze from the Orlando chapter of MOSSMOSIS invited me to talk about SharePoint WebParts and related issues. I was trilled to do this since I already started an AJAX project and it was great to have an opportunity to share some of my experience. The title of the talk was "SharePoint Web Parts - from Hello World to ASP.NET AJAX extensions", in which I gradually build up an AJAX enabled SharePoint WebPart and functional web tests for it.

MOSSMOSIS secured a great venue for their meetings (the downtown Orlando building of the Orange County School System) and provided excellent snack.

In addition I would like to thank all the MOSSMOSIS members, who came to the yesterday's meeting. You can download the slide deck and the samples from the links below:

SharePoint Web Parts - from Hello World to ASP.NET AJAX extensions:

Presentation slide deck

Code Samples

Dovizhdane!

Sunday, October 07, 2007

Microsoft releases source code for .NET Framework 3.5

Last week ScottGu in his latest post unveiled a plan by Microsoft to release the source code of .Net Framework 3.5 to developers under the Microsoft Reference License and to add automatic debugging support for the framework libraries in Visual Studio 2008. Needless to say this is one of the biggest steps the software giant is making to help developers be more productive. One apparent improvement is that we'll be able to see what actually happens in those sealed classes, but we'll also have the choice to learn from the code new developer techniques or why not write alternative solutions. I also anticipate that a plethora of developers from the community will be digging deep into the code making suggestions for improvements, finding bugs, writing books about new tips and tricks and helping Microsoft define the next versions of the .Net framework.

It is a win-win situation and a change of monumental proportions for the .Net developer community, which will certainly increase the popularity of the .Net framework and its reliability.

.Net developers of planet Earth - rejoice!

Dovizhdane.

Friday, September 21, 2007

SharePoint Resources, Types, Use and Deployment (Update)

For sometime I wanted to make an update to the deployment method for RESX files I proposed in a previous post. Even though there is nothing wrong with using custom jobs to deploy any file from a WSP solution to a SharePoint farm, I found about another option, which is a bit easier to implement. The code used to copy the resource files from the feature directory to the App_GlobalResources is pretty much the same, but this time not in a custom job, but directly in the feature event receiver.

SPWebApplication webApp =

this.Parent as SPWebApplication;

foreach (SPUrlZone zone in webApp.IisSettings.Keys)

{

// The settings of the IIS application to update

SPIisSettings oSettings = webApp.IisSettings[zone];

// Determine the source and destination path

sourcePath = string

.Format("{0}\FEATURES\{1}\",

SPUtility.GetGenericSetupPath(

"Template"),

featureName);

string destPath = Path.Combine(oSettings.Path.ToString(), "App_GlobalResources");

string[] filePaths = Directory.GetFiles(sourcePath, "*.resx");

// Copy the files

foreach (string filePath in filePaths)

{

string fileName = Path.GetFileName(filePath);

File.Copy(filePath, Path.Combine(destPath, fileName), true);

}

}

Then use feature stapling to activate the feature every time a new site from a given configuration is created. Feature stapling allows us to create associations between a feature and specific site configuration. To find out more about feature stapling have a look at this article: http://sharepointnutsandbolts.blogspot.com/2007/05/feature-stapling.html

Dovizhdane!

Wednesday, September 12, 2007

One Closed Chapter is a New Beginning

Today Global 360 released Insight360. This is an incredible product, which allows business analysts to create business models, run simulations, what-if scenarios and optimizations in a collaborative environment and finally deploy the optimized process in production. Read more about it here: http://www.ebizq.net/news/8449.html?rss

As a member of the R&D team, who worked on this product I am excited to see Insight360 "hitting the shelves". This is my first product release since I joined Global 360 and I am glad I was part of this project. I had the opportunity to work with some great people and learn quite a lot not only about SharePoint (which is used only for the collaboration part of the product named Team Studio), but also about agile development, testing and distributed teams.

The good news is that we have some great new products and features coming up next and my SharePoint affair is not coming to an end. The next project I stared working on is a collection of specialized AJAX enabled web parts, so expect some posts about ASP.NET AJAX integration with SharePoint.

Dovizhdane!

Monday, August 27, 2007

Jacksonville Code Camp 2007 summary

I would like to thank everybody who came to my session Developer's Introduction to SharePoint at Jacksonville Code Camp 2007. In this session I added an example of using RunWithElevatedPrivileges and a test code example based on WatiN, to create a functional test for the demo web part. You can download the slide deck and the code from here: JaxCodeCamp2007SiteContent.zip.

If you have questions about the code or the presentation post a comment to this message.

The code camp was packed with interesting sessions. The other sessions in the SharePoint track were:

  • What Every SharePoint Developer Should Know - Customization vs. Development by Andrew Connell (MVP & author)
  • Introduction to Web Content Management (WCM) in SharePoint 2007 by John Ross
  • Developing SharePoint 2007 with User Profiles, My Site and Social Networking by Brendon Schwartz (MVP)
  • Building Reusable CAML Queries in C# using CAML.NET by John Holliday (MVP & author)
  • Going Off Road With SharePoint - Using SharePoint from within your own application by Colin Borrowman

    Other session that I found interesting were:

  • Introduction to SQL Server 2005 Analysis Services by Brian Knight

  • The Role of an Architect by Jeff Barnes

  • And probably the most fun session of all to finish up the day was Robot Vision by Shawn Weisfeld. Shawn did a great job of explaining the algorithms for image analysis and finally set his I-Robot to chase Ken Tucker in the room. Very cool...

    Dovizhdane!

    Sunday, August 19, 2007

    Jacksonville Code Camp 2007

    Another code camp on the horizon. This is the first time I am going to be in Jacksonville and I am looking forward to meet the local geeks and to see one of the most beautiful cities in Florida. The area has very strong developer community and a lot of talented people. Some of them I already met at other code camps and TechEd and I expect to meet them and many others again. I am going to present an introductory session for SharePoint developers. There are still a lot of colleagues interested in exploring SharePoint and starting their first SharePoint project and I feel that the experience I gained in our last project has something to add to this topic. In addition to the usual starter samples I am adding an overview of all application development tools for SharePoint, emphasizing on the diversity of options and when to use them. In this session I am also adding one new topic - testing SharePoint applications. Since SharePoint applications can be very diverse, I am only scratching the surface by adding a sample about creating functional tests for SharePoint applications. It'll be a though week, with a trip to San Francisco and a whole week of meetings before that, but well worth the effort.

    Dovizhdane!

    Tuesday, July 24, 2007

    The new release of WSS SDK

    I was pleased to see some good additions to the WSS SDK in its latest release from 7/13. I am glad that Microsoft took into account a lot of community content and included information that was circulating blogs, CodeCamp sessions and newly released books for some time now. The articles, which explain how to create solutions and the principle of deploying and retracting solutions are much better. Since this is a topic I had to deal with couple of months ago, with almost no good resource of information, I find this new addition to the SDK of great value to developers that are starting with SharePoint.

    The additions to "What's New ...", "Technical Articles" and "Visual How Tos" make this a much better learning and reference tool. Check it out!

    Dovizhdane!

    Monday, July 16, 2007

    Tampa Code Camp

    One big Thank You to all of you that attended my Tampa Code Camp session "Developer's Introduction to SharePoint". The presentation and the code sample are available for download here : TampaCodeCamp2007.zip. If you have questions related to the sample post a comment to this message.

    The code camp was really big. The attendance was well above 300 and probably reaching 400. Keith Kabza and his team from the Tampa Bay .NET User Group did an amazing job organizing the event. The venue was loaded with modern AV and the logistics of the sessions, the lunch and ... the parties was flawless. Simply put, another great Florida code camp.

    Dovizhdane!

    Wednesday, July 11, 2007

    RunWithElevatedPrivileges, watch out for the site context

    Soon or later most SharePoint developers use RunWithElevatedPrivileges. We do that either to grant temporary access to files and folders not accessible by the current user or to execute some other action, which requires higher privileges. One thing I constantly forget about that always gets me with an "Access denied" error is when I omit the fact that the SPSite/SPWeb objects are initialized differently for different user contexts. Have a look at this code:

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
    SPWeb web = SPContext.Current.Web;

    // do something that's not allowed for the current user, but it is ok for the elevated user

    SPFile file = web.GetFile(restritedFileUrl);

    string readProperty = file.Properties["Name"].ToString();
    });

    Seems like done deal. Not so.... The problem is that the SPWeb object from the current context is initialized using the current user's credentials, so even though we run the code snippet with elevated privileges the actual access to the file is still restricted. To circumvent this we have to create a new SPSite/SPWeb object within the elevated code, where we run in the context of the elevated user. Then we can perform the restricted action. Since the SPSite/SPWeb objects are created explicitly we have to also dispose of them (more about why we need to do this here). The modified working code becomes:

    string siteUrl = SPContext.Current.Web.Url;

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
    SPSite sysSite = new SPSite(siteUrl);
    SPWeb sysWeb = sysSite.OpenWeb();

    // do something that's not allowed for the current user, but it is OK for the elevated user

    SPFile file = sysWeb.GetFile(restritedFileUrl);

    string readProperty = file.Properties["Name"].ToString();

    sysWeb.Dispose();

    sysSite.Dispose();

    });

    Access granted...

    Dovizhdane!

    Monday, July 02, 2007

    A busy month of learning and creating

    June turned out to be a very busy month. I started with a weekend in Orlando for the INETA summit, where I learned quite a bit of how user groups are functioning and contributing to the developer community. There were representatives from groups small and big, from all over north America. This meeting definitely inspired me of some activities that can spice up the live of the SCDNUG.

    Another huge event that came the week after was TechEd held in the Orlando convention center. This was the first time a attended such big developer event and I was really blown away by the amount of presentations, topics, self paced training options (and entertainment). I tried to stay loyal to SharePoint, but also wanted to expand in the upcoming new technologies from the software giant. There were many excellent sessions on LINQ, WCF, WPF and Silverlight. The overall opinion of our group was that LINQ is one of the biggest improvements in the .Net languages, along with the other improvements coming in Orcas. Needless to say, I am eager to get my hands wet. TDD was all over the place with interactive sessions, BOF and informal conversations in the VisuaStudio booth. IMHO the high point was delivered by Doug Seven who electrified the audience with an impressionable presentation and intro demo. After five days driving back and forth to Orlando and hours of sessions for five days, I closed the show attending a demo showing how to use AJAX.NET in SharePoint. Great plan, still hard to implement in real world applications.

    After this I thought I couldn't take it anymore and I don't want to talk about technology at least for a week. Well I was not so lucky, exploring the materials from the show, I found couple of promotional vouchers for certifications. Among them was one from the office launch event. I decided that with the least amount of work l can pass "70-541 Microsoft Windows SharePoint Services 3.0 - Application Development". So I took the extremely sketchy Preparation Guide and went through the list for about a day or two. Surprisingly I was able to get all pieces from the the SDK, MSDN and blogs, but I would not recommend this for somebody starting with SharePoint. The issue is that the knowledge is very fragmented and without a book or CBT to put a structure in all the bits, mastering SharePoint can be frustrating. Nevertheless I just got the word that I passed it. Who knows I may get back on the certification track again, even though I have mixed feelings about certifications and their value.

    Now I am getting ready for my second code camp session in Tampa. I am planning to give a SharePoint introduction for developers emphasizing on the whole picture, not only how to create a web part or how to deploy it, but how to get going with the the first simple SharePoint project. Code camps are great volunteer events from developers for developers. If you are interested in attending Tampa code camp you can register at http://www.tampacodecamp.com/

    Right after this on 07/18 is the SCDNUG meeting. We'll have a must see presentation by INETA guest speaker Brian Noyes, who is Microsoft Regional Director for the Mid-Atlantic region. The topic is "Connecting Applications with WCF". To register click here: https://www.clicktoattend.com/invitation.aspx?code=119083. See you there!

    Dovizhdane!

    Saturday, June 09, 2007

    Using satellite assemblies in SharePoint applications (with a twist)

    What I like about the way SharePoint stores localization resource files is that all strings are stored in central location. This makes the maintenance a bit easier (you don't need to hunt down all files that need translation) and allows ad-hoc changes without the need to recompile. On the other hand it's kind of hard to make strongly-typed notation (Resources.[file prefix].[resource name].) work and the time when the resources are auto-compiled can be a bit unpredictable.

    To find a solution, which allows me to create centralized language assembly for all strings and still be able to use strongly-typed notation I looked at another feature of the .Net framework - the satellite assemblies.

    Create a resource file in an assembly (e.g. Strings.resx), then add language specific version (Strings.en-us.resx), and in the build folder the compiler will create a sub folder with the locale id to store language a specific extension of the assembly. The limitation of this approach is that the automatically generated class is declared as private thus we cannot reference the resources from different modules in our SharePoint application.

    Trying to find a solution to this limitation I noticed one feature of the tool ResGen.exe, which compiles the resources. The command line parameter /publicClass allows us to generate the resources class as a public class.

    To make this work I added the following line to my pre-build commands:

    ResGen.exe /str:cs,<namespace> /publicClass "$(ProjectDir)Strings.resx"

    Then I added the main assembly and all satellite assemblies to the SharePoint solution manifest. In addition the rest of the application modules can use the localization assembly simply by adding a reference to it.

    <Assembly DeploymentTarget="WebApplication" Location="Localization.dll" />
    <Assembly DeploymentTarget="WebApplication" Location="en-USLocalization.resources.dll" />

    Compared to the use of global resources this approach does not allow the use of explicit expressions <%$ Resources:[filename prefix,]resource-key %> in ASPX pages, but I found that this is not a big limitation, especially if the development style of your team is more server side oriented.

    Dovizhdane!

    Thursday, May 31, 2007

    This is not another MAC ad

    Do you want to know what Steve Jobs thinks about the Mac ads? Have a look at this entertaining and unique joint interview with the leaders of the long time rivals.

    VIDEO: Steve Jobs and Bill Gates Highlight Reel

    Dovizhdane!

    Wednesday, May 30, 2007

    Why use SPJobDefinition in SharePoint Resources deployment

    Recently Matthias Glubrecht and other readers of my post SharePoint Resources, Types, Use and Deployment asked me why do I use a custom SPJobDefinition to deploy resx files to the App_GlobalResources folder. The reason is simple (I remember when I asked Vincent Rothwell the same question and he was kind to explain this to me), the event receiver events (FeatureActivated etc.) are only invoked on the server where the feature gets activated not on all farm servers.

    In other words if we need to make modifications to the objects stored in the content or configuration databases of the SharePoint farm, we can use directly the event receiver event handlers. The situation is a bit different when we need to modify objects outside of the SharePoint database, such as the files system, files or the resources (resx) files. In order to invoke the update on all front-web servers need to create a custom SPJobDefinition. One exclusion of this rule is the web.config modification class, which synchronizes web application configuration files via the SharePoint DOM.

    Another benefit of using SPJobDefinition is that the timer service runs with a higher privileged account, where as the event receiver event handlers are invoked in the context of the current user.

    Dovizhdane!

    Wednesday, May 16, 2007

    Creating Dynamic Breadcrumbs in SharePoint ASPX Pages

    If you already played with custom layouts pages in SharePoint you probably noticed that the breadcrumbs are missing. In a recent post Vincent Rothwell explains how to enable the breadcrumbs in ASPX pages placed in the LAYOUTS folder of SharePoint. Since the stock layouts pages use the SPXmlContentMapProvider, which in turn uses the layouts.sitemap file located in the _app_bin folder, if we add entries for the newly added layouts pages we'll get a rudimentary breadcrumb fixed to one level under the site node. The breadcrumb is in this format: site > custom page. This is one good solution and works fine if this format is satisfactory for your project.

    However this is not helping us if we need a dynamic breadcrumb, which will change to represent the logical structure of the site. For example if the ASPX page handles a list item in a specific way, I would like the breadcrumb to properly display the breadcrumbs. For example site > list > folder > item > custom page.

    One way to go is to create a custom SiteMapProvider, but this requires changes in the master pages and a bit more code. I was looking for a solution, which works with the standard applications.master page and can be used to modify the breadcrumb of any layouts page.

    Another solution is to attach to the SiteMapResolveEventHandler. This is not a secret and there are many samples for regular ASPX pages (Raj thanks for pointing this out!), but in SharePoint context there are several twists, which I would like to illustrate with this sample.

    First let's attach our event handler to the provider and do some parameter validation.

    private SPWeb web;

    private SPListItem currentItem;

    protected override void OnInit(EventArgs e)

    {

    base.OnInit(e);

    SiteMap.Providers["SPXmlContentMapProvider"].SiteMapResolve +=

    new SiteMapResolveEventHandler(provider_SiteMapResolve);

    string listId = Request["listId"];

    string itemId = Request["itemId"];

    if (string.IsNullOrEmpty(listId) && string.IsNullOrEmpty(itemId))

    {

    throw new Exception("Invalid item ID or list ID.");

    }

    else

    {

    web = SPControl.GetContextWeb(Context);

    SPList list = web.Lists.GetList(new Guid(listId), true);

    currentItem = list.GetItemById(int.Parse(itemId));

    }

    }

    Since the SiteMapResolve event applies to all pages we want to make sure that we detach the event handler:

    protected override void OnUnload(EventArgs e)

    {

    base.OnUnload(e);

    //detach from the static SiteMapResolve event and restore localization mode

    SiteMap.Providers["SPXmlContentMapProvider"].EnableLocalization = true;

    SiteMap.Providers["SPXmlContentMapProvider"].SiteMapResolve -=

    new SiteMapResolveEventHandler(provider_SiteMapResolve);

    }

    Because this event gets fired on all pages that subscribe to the event, we want to make sure that our code alters only our page. This is why we add the IsSamePage function, which can apply different criteria to determine whether our page is currently loading.

    /// <summary>

    /// Determines whether the two contexts are equal and, therefore,

    /// whether the SiteMap.SiteMapResolve event should be fired.

    /// </summary>

    protected virtual bool IsSamePage(HttpContext context1, HttpContext context2)

    {

    //by default, the contexts are considered the same if they

    //map to the same file and the same listid/itemid

    return ((Server.MapPath(context1.Request.AppRelativeCurrentExecutionFilePath) ==

    Server.MapPath(context2.Request.AppRelativeCurrentExecutionFilePath)) &&

    (context1.Request.QueryString == context2.Request.QueryString));

    }

    Now lets do the real work and modify the breadcrumb. In this sample I only add the name of the list, which contains the item and the name of the item itself. A logical extension is to add the folders in the path of an item, but once you get the idea you can change the code the way it fits your needs. The event handler should return the last node in the tree. If an exception occurs, we just ignore all changes.

    /// <summary>

    /// Overrides the breadcrumbs with a new one in the format

    /// [site]>[repository list]>[process folder]>[page title].

    /// </summary>

    SiteMapNode provider_SiteMapResolve(object sender, SiteMapResolveEventArgs e)

    {

    if (!IsSamePage(Context, e.Context) || currentItem == null)

    {

    e.Provider.EnableLocalization = true;

    return e.Provider.CurrentNode;

    }

    SiteMapNode pageTitleNode;

    SiteMapNode listNode;

    try

    {

    // Trun off localization, so that the custom nodes do not get overwritten

    e.Provider.EnableLocalization = false;

    // Clone some node to get a valid node object and modify it.

    listNode = e.Provider.RootNode.ChildNodes[0].Clone();

    listNode.Url = currentItem.ParentList.DefaultViewUrl;

    listNode.Title = currentItem.ParentList.Title;

    listNode.ChildNodes = new SiteMapNodeCollection();

    // Add as many new nodes as you need here

    pageTitleNode = new SiteMapNode(e.Provider, Guid.NewGuid().ToString());

    pageTitleNode.Title = Title.Text;

    listNode.ChildNodes.Add(pageTitleNode);

    pageTitleNode.ParentNode = listNode;

    }

    catch (Exception ex)

    {

    return e.Provider.CurrentNode;

    }

    return pageTitleNode;

    }

    There are two tricks in this code that I want to point out. The first one is that we cannot add a new root (breadcrumb) node to the provider since the property is read only and our page does not have an entry in layouts.sitemap. This is why we use any of the page nodes defined in the layouts.sitemap file (thus eliminating the need to alter layouts.sitemaps). Since the default format is site > custom page, we get the site node automatically. What we need to do next is to modify the leaf node and extend it with as many node levels as we need. The second caveat is the line where we disable provider localization. This is needed, so that the modified text does not get overwritten.

    In the next lines we overwrite the URL and the text for the first node with the URL and the name of the list, which contains the item. Next we add an additional node to display the name of the item.

    To make things even easier take out the class from the code-behind file and compile it in a separate assembly, then reference this class from any "List Item" page to get the same breadcrumb behavior.

    And finally a link to the source code.

    Dovizhdane!

    Monday, May 14, 2007

    Disable size limits for wsp (cab) files

    Couple of days ago we added a big zip file to our SharePoint deployment and out of the sudden the solution started behaving strangely. After some trial and error Robin found out that every time we cross the 360KB limit we have a problem. Wait, 360KB this rings the bell, but it was such a long time ago. What was it? You guessed it right the default limit for file size of makecab.exe is 360KB the size of 5.25 inch diskette. Talk about legacy support... To disable all kinds of limitations I added these lines to my DDF files and everything worked fine again.

    .Set CabinetFileCountThreshold=0
    .Set FolderFileCountThreshold=0
    .Set FolderSizeThreshold=0
    .Set MaxCabinetSize=0
    .Set MaxDiskFileCount=0
    .Set MaxDiskSize=0

    You may wonder why would I need a zip file in my solution, but that's another post in the works. Stay tuned. Dovizhdane!

    Tuesday, April 10, 2007

    Where are my SharePoint features?

    On several occasions colleagues and some of my blog readers asked me questions about how to locate a particular SharePoint (WSS v3 or MOSS 2007) feature. In most cases the feature was placed correctly in the FEATURES folder in the 12 hive, but they couldn't find it in the SharePoint UI thus they were not able to activate it. Since this happened more than three times it calls for a good old blog post. In this post I am going to write about the different types of features and how to access them from the SharePoint UI.

    Let's assume you already deployed your feature using either a SharePoint solution or by using stsadm -o installfeature -filename [feature folder]feature.xml . The feature files are located in the folder ..\12\TEMPLATES\FEATURES\[your feature name]\. So you followed the SDK or the sample and it looks like all is fine until you open the Site Features page of your target web site and the feature is not listed there. What's going on?

    It all depends on what is the scope of your feature. There are four feature scopes, which deploy the feature on four different levels in the farm hierarchy and as a result are managed from different web pages within the site settings and the SharePoint Central Administration.

    The Site scope installs the feature on a site collection level, which makes it available only on the Site Collection Features page accessible from the Site Actions menu. This menu however is only available for the root site of a site collection and is not displayed in the sub sites, which is a typical source of confusion.

    The Web scope installs the feature on every web site including the root of the site collection in the Site Administration section as shown above.

    The next scope level is WebApplication. These features are applied to all sites in all site collections of the web application and they can be activated and deactivated from Central Administration > Application Management > Manage Web Application Features.

    Finally the features with the Farm scope are are accessible from Central Administration > Operations > Managers Farm Features.

    No more lost features...

    Dovizhdane!

    Thursday, March 22, 2007

    SharePoint Resources, Types, Use and Deployment

    In the recent weeks one of my tasks was to work on the localization of a WSS solution and deployment of resources to WSS sites. I found that this topic is still not well explained and there are not too many sources that describe the specifics of using and deploying resources in WSS 3. In this post I'll explain the differences in the use and deployment of several types of resource files.

    Types of WSS Resources

    There are two groups of resource files in WSS. The first one includes files used during provisioning of sites and features. This group I'll call provisioning resources. The second group includes resource files used by ASPX pages and assemblies at run-time. This group respectively I'll name run-time resources.

    The provisioning resources are located in the 12 hive in ..\12\Resources. In WSS the default provisioning resource file is core.resx. This file is used in site definitions (one.xml) files, features, list definitions etc. For example you can open any of the existing site definitions to see how this works. The picture below shows the first rows of the ONET.XML file of the Wiki site definition.

    In a WSS feature there are three options for using localized strings from resource files. The default location for the feature's resources is ..\12\TEMPLATE\FEATURES\[FeatureName]\Resources\Resources.[Culture].resx and the strings can be referenced with $ Resources:resource-key, omitting the resource file prefix. Another option is to use the resources in the ..\12\Resources folder, which are available with the full explicit expression form $ Resources:[filename prefix,]resource-key, where the resource file name prefix is specified. The file name prefix can be omitted when the attribute DefaultResourceFile contains a name prefix of a file in ..\12\Resources folder. The attribute RequireResources of the feature element provides additional control over the activation of localized features (see WSS SDK for more info).

    Nevertheless the provisioning resource files are not accessible from the ASP.NET web sites. This is where the run-time resources come to play. These files are used in vanilla ASP.NET sites and are located in the web application folder under ..\wss\VirtualDirectories\[port]\App_GlobalResources. They are compiled automatically by the .Net framework in the Resources namespace. These resources are available in assemblies and directly in ASPX pages. To access them from the code use the strongly-typed notation Resources.[file prefix].[resource name]. In ASPX pages use the explicit expression <%$ Resources:[filename prefix,]resource-key %>. The default WSS resource file in this category, used by all WSS sites, is wss.resx.

    Deployment of Provisioning Resources

    The deployment of provisioning resources can be accomplished using WSS solutions. Unfortunately neither of these deployment facilities support the deployment of run-time resource files directly to the App_GlobalResources folder. In the following samples I'll demonstrate how to access and deploy both types of resource files.

    The WSS solution manifest contains two elements with names that imply to have something to do with the deployment of RESX file. They are <ApplicationResourceFiles> and <Resources>. Unfortunately they are not really helpful and basically can be ignored.

    To deploy provisioning resources available to all site definitions, features, list definitions etc. use the <RootFiles> element in the WSS solution manifest. The target folder for this element is the 12 hive ..\12\. The files in the example below will be copied to ..\12\Resources\.

    To deploy feature specific provisioning resource files, inside your feature's folder, create a sub folder named Resources and rename the resource files to Resources.[language-locale].resx. Remember to omit the file prefix in the string expression ( e.g. $Resources:resource-key; ).

    Deployment of Run-Time Resources

    Global WSS run-time resources reside in ..\12\CONFIG\Resources. This copy of the files is not used directly. At the time a new web application is created the content of this folder is copied over to ..\[port]\App_GlobalResources. If your organization has one set of localization files used in multiple applications this is the place to put them. You can use the <RootFiles> element in a similar way as described above to deploy such files using WSS solution. However it is very rare that a new web application will be created for a single site or solution. Another option is to use the use stsadm command with the option copyappbincontent to copy the content of ..\12\CONFIG\Resources (among other files and folders) to App_GlobalResources.

    None of the above described approaches allows developers to deploy resource files at the time the site or the feature are provisioned. To circumvent the lack of such functionality I hooked up a custom SPJobDefinition to the FeatureActivated event of its event receiver. This is becoming common practice, when it comes to extending the WSS solutions and WSS features. (I got inspired by Vincent Rothwell and his post about extending breadcrumb for pages in _layouts). The job copies the files from the feature's folder to the App_GlobalResources folder of the current web application. Here is how it works.

    First let's create a feature to deploy the resource files. The feature defines the event receiver and the assembly.

    Next let's create our custom job definition. The constructors look like this:

    The first constructor is required and used internally. In the second constructor we simply initialize the source path using the feature's physical path.

    The next step is to define the overloaded Execute method, which will copy the files from the feature's folder to the App_GlobalResources.

    Once we have the custom job definition, lets hook it up to the events of the feature's event receiver. On the FeatureActivated event we are going to create one new task from our newly defined type and submit it for one-time immediate execution.

    As Andrew Connell suggests in this post, before we create the job, we make sure to delete existing instances of the same job type for the current web application. This way we do not end up with competing jobs performing the same action. In a similar train of thought it is nice to clean up the job when the feature is deactivated. So let's add some code to the FeatureDeactivating event.

    One future addition to the custom job class will be to delete the deployed resource files, when the feature is deactivated. Since the feature is related to the WSS solution, when the solution gets retracted, the files will be cleaned up nicely as well. The feature can also be extended to be locale aware and deploy only specific resources.

    Update 9/21/2007: In this post http://www.mikhaildikov.com/2007/09/sharepoint-resources-types-use-and.html I write about slightly different way to deploy RESX files using feature stapling, which is a bit simpler to implement.

    Click here to download a complete sample project.

    Got localized?

    Dovizhdane!

    Monday, March 19, 2007

    Inserting GUID directly into the code

    I have always used guidgen.exe to generate GUID. It comes directly with VS and it is available out of the box. This tool generates the GUID in four different formats, unfortunately all of them contain some extra characters, plus you have to copy & paste it to your code and clean it up.

    Torben suggested this VS macro, which actually inserts a clean, capitalized GUID directly where you need it. Simple and convenient.

    Sub InsertGuid()

    Dim textSelection As TextSelection

    textSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection)

    textSelection.Text = System.Guid.NewGuid.ToString().ToUpper()

    End Sub

    One more little improvement to my all precious development VM environment.

    Dovizhdane!

    Monday, February 26, 2007

    Acquired Taste of Vista

    Definition: acquired taste

    Something one learns to like rather than appreciates immediately.

    This weekend I finally got some time to make the step and upgrade to Vista. There's been a lot of talk about what it does better and what it does not. Nevertheless I am getting the impression that the media and some colleagues are concentrating a bit too much on the negatives. Well there are issues primarily with drivers and unsupported hardware, but for fairly new machines the new operating system actually brings a wealth of benefits. One to mention ... the new driver model utilizes far better the new multimedia hardware and multi core systems.

    The first step was to run the compatibility assessment. The Vista Upgrade Advisor checks the hardware and points out issues that prevent the installation from completing. In my case I had to uninstall only an older version of Norton Antivirus. Other than that I've got couple of warnings about unsupported software, but most of them turns out work fine. So once this was done I moved forward with the upgrade.

    In stark contrast to previous versions of Windows, which were some sort of marketing slideshow, the Vista upgrade has a very clean interface and I like that. Set the type of upgrade and the time zone and leave the PC for an hour or two to do its job. That's exactly what I did. Left the PC and got back to my game with my son. Sometime later I was greeted by the new face of Windows.

    The "Aero" interface, the eye candy everybody is talking about, strikes immediately with its rich visual effects and smoother look. Definitely more than eye candy. Each window runs in its own memory segment and the overlapping screen refreshes of the past are gone. I realize not all flavors of Vista are shipped with Aero, but maybe not all users will appreciate the dynamic visual effects any way. In only a few clicks I started noticing UI improvements, which I know will make my workday easier. The Welcome Center gives some good overview of new and old features and its interface is organized in different levels of dept. This makes learning gradual and paced to your needs. The sidebar nicely fits the widescreen of most new laptops and makes use of the width of the screen. A rich library of gadgets already exists and there are numerous samples on how to create one for developers of all skill levels.

    Needless to say security has many improvements, soo many that your head spins. The most interesting for me are Windows Defender and User Account Control (UAC). Windows defender will stop or disable suspicious programs that are trying to run at startup and classify the software, so that you can decide what to allow running and what not. Finally something that tells the user in a simple way what programs run at start up on your PC and applying an algorithm to determine if this is appropriate.

    UAC is by far the most controversial measure of all. It is really reassuring that something in your PC is watching for actions that require access to core system resources. For most users this should be a rare occurrence and probably a good thing. But the way I see it, most important of all is that UAC will not allow machines installed with default settings sitting somewhere on the Net to be hijacked. This only will drastically improve the security of Internet as a whole.

    Nevertheless for developers UAC is a bit of a pain. True, we have to live with it to make sure our apps run properly for the target audience, but MAN that's a lot of additional clicks and keystrokes. My wrists and hands are already giving me signals of pain when I overdo it and UAC is not going to make it easy for them either. An advertisement of a major competitor characterized UAC as a secret agent that puts to question each and every action th PC makes and with all honesty they hit the nail on the head. After several decades of AI actively being part of science and computing it seems very drastic that Microsoft decided that only humans can determine whether one action is dangerous for your PC or not. This is a pretty strong message and it might work, but would it?

    My guess is that we are going to see the evolution of UAC very soon. People just don't like the hassle. They would much rather purchase software that claims to do the job of UAC than "carefully read each message" and click OK. Many will simply disable UAC. In other words if Microsoft doesn't come up with a solution that at least allows the user to save her answers on per program level (i.e. educate UAC), the industry will catch up fast and let the people enjoy their AERO interface. Altogether UAC is a huge leap in the right direction and there is no turning back.

    Other major improvements come in the area of backup and recovery. I installed Vista and immediately created a full PC backup to an USB drive. Amazingly the format of the image is VHD. Great, now you can actually crank up an old backup in a VM and retrieve files. It would be best if you can right click on the VHD file and mount the virtual drive to the host PC. In addition the recovery console in Vista actually can help you (how many times did you use the one in XP anyway) and you can fully restore from a backup. I didn't try this yet, but the prospect of finally having reliable full backup embedded in the OS is great.

    Other features that momentarily caught my attention are the Start menu, the Services tab in Task Manager, the navigation in Explorer and Add/remove programs shortcut in My Computer, which by the way is called Computer.

    The start menu is not cascaded anymore and using the search it is incredibly easy to find not only documents but execute programs as well. The services tab in Task Manager needless to say is very convenient for developers and the likes to easily access the service list and start/stop them or jump to the underplaying process. I loved the add/remove shortcut on the toolbar of Computer that opens the applet with one click. No more drilling in control panel.

    The cherry on top of my cake is one little gadget I really will use a lot for documentation and blogging - the "Snipping Tool". Finally it is easy to take snapshots from any part of the screen (not only program windows using the ancient PrtScr). There are probably tons of low cost tools out there that do the same, but having this tool within the OS is very helpful.

    Now don't ask me why I started writing about taste and wound up ranting about Vista. One thing we humans take always with resistance is change. The bigger the change the bigger the resistance. The stronger the taste the more time you need to enjoy and appreciate it. Vista concentrates the collective wisdom of thousands of people about the way personal computing should work in the future. It is possible that not every decision they made was right on target, but even if they got closer than their previous attempt (and believe me they did) that's called progress.

    Install Vista, give it some time to acquire the taste of it, and focus on the future...

    Dovizhdane!

    Thursday, February 22, 2007

    SCDNUG February Event

    Yesterday I presented Windows SharePoint Service 3 for Developers to the Space Coast .Net user group. The PowerPoint file is available at SCDNUG web site. We talked about some of the most important improvements in WSS 3. The agenda was:

    • SharePoint products and acronyms
    • The tree faces of SharePoint
    • SharePoint & ASP.NET
    • Improved deployment tools
    • SharePoint Administration
    • Summary

    Thanks to the usual suspects in SCDNUG and the couple of new people that came.

    Dovizhdane!

    Friday, February 16, 2007

    Configuring the breadcrumb for pages in _layout and how to deploy the map using features

    While working on custom pages located in the _layouts folder, I noticed that the breadcrumb was missing. I found this great post which explains not only how to update the site map, but also suggest a method of merging the site map with custom site maps.

    http://blog.thekid.me.uk/2007/01/17/configuring-the-breadcrumb-for-pages-in-_layouts/

    Dovizhdane!

    Monday, February 12, 2007

    South Florida Code Camp (continued)

    As I previously said the SharePoint track at the South Florida Code Camp had a full day of sessions. All of them very interesting and presented by some of the best regional SharePoint MVPs. Here is a list of all other sessions:

    The organization of the event was flawless and for a FREE event the value was incredible. Now that this Code Camp is over I am looking forward to the next one in Orlando.

    Dovizhdane!

    Saturday, February 10, 2007

    South Florida Code Camp

    What a great event! The SharePoint track at the South Florida Code Camp was really packed with interesting presentations. I was presenting my session "Understanding Windows SharePoint Services Framework", which shows how to create a WSS solution from scratch. (Unfortunately VSeWSS was not ready for this event and was not presented).

    One big "thank you" goes to all that attended the session! Your feedback is very important for me.

    You can download the session materials from here SFCodeCamp_WSS_SolutionFramework.zip, all materials are posted on the Code Camp website here: http://codecamp07.fladotnet.com/

    Dovizhdane!

    Wednesday, February 07, 2007

    I'll wait until SP1 comes out...

    Couple of days ago I received an E-mail from the IT department. The subject was Microsoft Vista and Office 2007. In the E-mail he takes a position that became quite popular lately: Don't bother installing newly released software because we are not going to support it until SP1 comes out. The usual IT concerns about things not working as expected and being so different that actually nobody can use them and so on... This is not the first time I see IT departments taking such position and in many occasions this is a good rule of thumb to let "the other guys" figure it out first. Big corporations have a large number of installed base and run complex applications so this may be the way to go. On the other side of the spectrum the small guys are often too fragile to make big investment in a technology before it becomes mainstream, so this approach might be OK for them too.

    Nevertheless I cannot justify such position when it comes from a mid size stable software company, which on top of this claims to be innovation leader and Gold Microsoft Partner. It just does not fit.

    One other principle of software development I recall is dogfooding. This is when you use internally the software you create and sell to improve further your development. In the same line of thought this principle is applicable for third party software you integrate with. Naturally Microsoft Vista and Office 2007 fall in that category, since we already develop software running on these platforms.

    So my question is: If a software company wants to be on the fast track of innovation, does it wait until SP1 of Product-My-Platform comes out, or starts its evaluation and use as the RTM (or even BETA) release become available?

    Dovizhdane!

    Monday, February 05, 2007

    SafeControl Registration in WSS Solutions

    While getting ready for the South Florida CodeCamp session on WSS Solution Framework, I've noticed an interesting feature of the deployment mechanism related to the registration of SafeControls. Prior to this little discovery I was using Lutz Roeder's .NET Reflector to obtain the full assembly name including version and public token. It turns out that in the WSS Solution Framework we only need to specify the name of the assembly. The framework will automatically detect that the assembly is strongly signed and fill in the Assembly attribute of the SafeControl element with the strong name of the assembly in the web.config entry. For example, if we specify in manifest.xml:

    <Assembly DeploymentTarget="WebApplication" Location="myassembly.dll">
    <SafeControls>
    <SafeControl Namespace="mynamespace" TypeName="*" Safe="True" />
    </SafeControls>
    </Assembly>

    In the web.config file it'll be resolved to:

    <SafeControl Assembly="myassembly, Version=1.0.0.3, Culture=neutral, PublicKeyToken=b62731c11ae57915" Namespace="mynamespace" TypeName="*" Safe="True" />

    This saves some time updating the solution manifest.xml file.

    Dovizhdane!

    Friday, February 02, 2007

    Configuring URLMembershipCondition for individual assemblies and the $AppDirUrl$/bin/ path for WSS solution.

    In a previous post I described how to configure CAS within WSS solution. At the time I used a membership condition based on the key blob. This works fine for signed assemblies and allows us to create one permission set for a group of assemblies. In our deployment however we decided to remove the assembly signatures, since this interferes with other projects. Trying to find out what other conditions we can define I used the name of the assembly only, so that the CAS section in the manifest.xml file looked like this:

    ...

    <CodeAccessSecurity>
    <PolicyItem>
    <Assemblies>
    <Assembly Name="myassembly.dll"/>
    </Assemblies>
    <PermissionSet class="NamedPermissionSet" Name="MyPermissions" version="1">

    ...

    This works and in the custom configuration file it translates to:

    ...

    <CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="solution.wsp-1c4cffbe-f1ed-428e-afde-c82d59516da7-1">
    <IMembershipCondition version="1" Name="myassembly" class="UrlMembershipCondition" Url="$AppDirUrl$/bin/myassembly.dll" />
    </CodeGroup>

    ...

    This is great, but there is still a lot of typing to create and maintain permission set for each assembly. I wish there was an option to define UrlMembershipCondition for group of assemblies in the $AppDirUrl$/bin/* path. So I created the permission set for the assembly "*" and the result was this membership condition:

    ...

    <IMembershipCondition version="1" Name="*" class="UrlMembershipCondition" Url="$AppDirUrl$/bin/*.dll" />

    ...

    Looks like it will work fine? Unfortunately the config file parser complains about the *.dll part of the URL attribute, so no luck here either.

    I guess, I am going back to defining individual permission sets for each assembly.

    Dovizhdane!