Wednesday, June 19, 2013

SharePoint 2013: Unexpected response from server. The status code of response is ’500′. The status text of response is ‘System.ServiceModel.ServiceActivationException’

copyright from: http://sharepointthing.wordpress.com

After having this issue on newly installed SharePoint 2013 farm in production environment, I figure it out that Single server is running out of memory. Especially, thanks to one new process noderunner.exe.
Noderunner.exe is the new executable of search service on SharePoint 2013. This process can’t turn it off because Search is one of essential service application in SharePoint 2013, and it is integrated in many features. So, there are some things you can do to reduce the impact of Search on your system.
Solution 1
Reduce the Search Service Performance Level with this PowerShell command:
Set-SPEnterpriseSearchService -PerformanceLevel Reduced
or
Set-SPEnterpriseSearchService -PerformanceLevel PartiallyReduced, which is in between reduced and Maximal
Solution 2
Limit the Memory Footprint of NodeRunner.exe is one thing that is not so recommended. There is a configuration setting for NodeRunner.exe’s configuration file that can limit RAM usage of a single process to specific value in megabytes.  This configuration file is located at: C:\Program Files\Microsoft Office Servers\15.0\Search\Runtime\1.0\noderunner.exe.config.  The configuration setting is under the nodeRunnerSettings node and it’s called memoryLimitMegabytes.  Its default value is 0 (unlimited).  Every time you change it, you’ll need to restart all of the noderunner.exe processes.
On some blogs I have found that noderunner.exe has memory leak and this is known bug in SharePoint 2013

Thursday, June 13, 2013

Document ID Feature

Copyright from:  http://www.codeproject.com

Introduction

In this article we can explore the Document ID feature and how to programmatically retrieve documents based on the IDs.

Scenario

Your customers are using Document Libraries for creating, updating and sharing documents. A problem could arise when the same document could exist in multiple libraries with the same name. There should be a way to identify the document using some Unique ID so that the document could be managed effectively independent of the location.
Document copy 1
 
Document copy 2

Solution

SharePoint already contains the Document ID service feature which could be used to address this problem. Document ID Service is a Content Management feature and explicit activation is needed in the site collection level. Once activated all the documents in the site collection will be assigned a unique ID.
Note: The Document ID is different from Record ID.  Additionally List items cannot be assigned Document ID.

How to enable Document ID Service?

You have to go to the Site Collection Top Level Site and choose Site Actions > Site Settings > Site collection features.
In the appearing page Activate the Document ID Service feature.
On activating the feature a Timer Job will be assigned to generate Document ID for all the existing documents.
You can make the Timer Job run immediately by going into Central Administration > Monitoring > Check Job Status > Scheduled Jobs link.
Click on the Job named Document ID assignment job and in the appearing page click on the Run Now button. This should create Document ID for all the documents in site collection libraries.

Document ID Settings

Once the feature is activated you can change the settings through Document ID Settings link as shown below. This link is only visible once you enable Document ID Service feature.
In the appearing page you can change the Settings like Prefix for generating ids for example: COM-DOC-1, COM-DOC-2 etc. You can assign a prefix of 4 to 12 characters.
Click the OK button to continue. You need to run the Timer Job again to see the immediate assignment of IDs.

Viewing the Document ID

Once the Document ID is assigned you can go back to any library in the Site Collection and use the View Properties menu item to view the ID associated.
In the appearing dialog the Document ID is shown.
 
Note: Copying documents will create new Document ID for the new document. Moving document will retain the original Document ID.

Using Document ID Programmatically

Now we can use Server Object Model to get a document using the Document ID. Please follow the following steps to achieve the same:
Step 1: Create a new SharePoint 2010 > Console Application
Step 2: Add reference to Microsoft.Office.DocumentManagement assembly
This assembly should be residing in the 14hive\ISAPI folder. You can use the Add Reference dialog box > SharePoint tab for locating the same.
 
Step 3: Create the code to fetch by Document ID.
You have to use a DocumentIdProvider instance to perform the same. The following code fetches the Document URL based on the Document ID.
static void Main(string[] args)
{
    SPSite site = new SPSite("http://localhost/sites/newsitecollection");
    DocumentIdProvider provider = DocumentId.GetProvider(site); ;
    var result = provider.GetDocumentUrlsById(site, "DOCUMENT-4-1");
    Console.WriteLine(result[0]);
    Console.ReadKey(false);
}
You need to change the Site URL and Document ID string according to yours. On running the code the URL of the Document is shown.
With the document URL in hand you can write your own code to manipulate it.
Note: You can also use the DocumentId.FindUrlById() method to retrieve the URL as a string.

References

Summary

In this article we have explored the Document ID feature and retrieving documents based on the Unique ID.
Following are the points to summarize with:
  • Document ID Service is a Content Management Feature
  • A Site Collection Level Feature
  • Once activated all documents are assigned unique IDs
  • Programmatically we can retrieve document by ID
  • Prefix can be used along with the Document ID
  • A Timer Job is responsible for assigning the IDs

Details about how Document ID Service is activated

copyright from: Chun Liu on SharePoint

You may have found that Document ID Service is a very interesting feature. Sometimes you activate it and it just works as expected. But sometimes you activate it and it doesn’t work immediately. A typical example is to activate it on a team site and a publishing portal site. On the team site, it works immediately, but on the publishing portal site, it doesn’t work immediately. So what is the reason behind?
The reason why this feature works like that is related to how it is activated. Basically, when we activate this feature, it will check if the current site collection is a big site or not. If the site collection is not big, it will just enable the DocId on the site collection and register a work item for the Document ID Assignment timer job (DocIdAssignment). But if the site collection is too big, it will just register a DocIdEnableWorkItem for the Document ID Enable/Disable timer job (DocIdEnable). So to big site, it relies on the DocIdEnable timer job to enable the DocId. But you may find even if you run this timer job immediately after the feature is activated, the DocId is not enabled. It is because when the DocIdEnableWorkItem is added to the site by the feature activation, it has been specified to be executed 30 minutes later to avoid the potential conflict. You can check the real scheduled delivery time by querying ScheduledWorkItems table in the content db. So the DocId will only be enabled when you run DocIdEnable timer job after the scheduled delivery time. For example, suppose you activated DocId feature on a publishing portal at 8:00am, the DocIdEnableWorkItem was scheduled to be delivered at 8:30am. If you ran DocIdEnable timer job before 8:30am, nothing really happened. Only when you ran it after 8:30am say 8:35am, DocId was enabled then.
The final question is how big a site collection is big? The boundaries are maximum 1 web/site, 40 lists/web and 20 doclibs/web. A publishing portal is too big because by default it has 3 webs. The OOTB document center is OK because by default it has 1 web, ~30 lists and ~15 document libraries. The numbers are hard coded and, so far as I know, there is no way to change them

Tuesday, June 11, 2013

SharePoint 2010 Development Environment on Windows 8 RP

copyright from: http://blog.mikehacker.net
Disclaimer:  The information found in this blog post is not endorsed, recommended, or supported by Microsoft.  If you run into any issues with this configuration you are on your own!  You have been warned.
This blog post outlines how you can get SharePoint 2010 running on Windows 8 RP for development purposes.  I put this together as a way to test out Visual Studio 2012 RC with SharePoint 2010 on Windows 8 RP.
To get started, please review the MSDN document called Setting Up the Development Environment for SharePoint 2010 on Windows Vista, Windows 7, and Windows Server 2008.  These are the basic steps required for getting SharePoint 2010 running on Windows 7.  To get SharePoint running on Windows 8 RP there are a few additional steps which I have outlined below.  Some of the steps will reference information in the MSDN article linked above.
  1. Download and Copy the SharePoint installation file to a folder (such as c:\SharePointFiles) on the computer where you are installing SharePoint and doing your development.  The SharePoint installation file should be a single .EXE file such as OfficeServer.exe.
  2. Extract the installation files by opening a command prompt window and then typing the following command at the directory location of the folder where you copied the installation files in the previous step.    OfficeServer.exe /extract:c:\SharePointFiles
  3. Using a text editor such as Notepad, open the installation configuration file, config.xml, located in the path c:\SharePointFiles\files\Setup\config.xml and add the following line inside the tag:
  4. Save the configuration file.
  5. Review the configuration file.  It should look similar to the XML block shown in Step 2 sub-step 5 in this document.
  6. Install the following prerequisites:
    1. Microsoft Sync Framework
    2. Chart Controls
    3. Filter Pack – Located in the c:\SharePointFiles\PrerequisiteInstallerFiles\FilterPack folder
    4. SQL Server Analysis Services ADOMD.NET
  7. Enable Windows features by running the command shown in Step 2 sub-step 8 in this document.
  8. Manually enable the Windows Identity Foundation feature by:
    1. Go to the start menu (press the Windows key on the keyboard)
    2. Type: “Windows Features”
    3. Click on the Settings shown below the search box
    4. Click on the Turn Windows Features On or Off option on the start menu
    5. Check the Windows Identity Foundation 3.5 option and then click OK.
    6. Wait for the feature to be enabled.
  9. Open Internet Information Services Manager and expand the server node in the left tree menu to expose the Application Pools grouping.
  10. Select Application Pools in the left menu and then click on the Set Application Pool Defaults… action in the right menu.
  11. Set the .NET Framework version to V2.0 and then click OK
  12. Select the DefaultAppPool from the list of application pools and then click on the Basic Settings… action in the right menu.
  13. Set the .NET Framework version to .NET Framework v2.0.50727 and then click OK.
  14. Run the SharePoint 2010 installer by typing the following at the command prompt:  c:\SharePointFiles\Setup.exe
  15. Accept the Microsoft Software License Terms
  16. On the Choose the installation you want page, click Standalone to install everything on the developer workstation.
  17. After the SharePoint files are installed you will be presented with the option to run the SharePoint Products and Technologies Configuration Wizard.  You should allow this to run.  If you do not run the Wizard now you can run it at a later time.  The SharePoint installation is not completed until the Wizard is run.
  18. One the configuration Wizard completes you will see your new SharePoint 2010 Site.
Note:
  • SharePoint 2010 Only works with application pools that are set to version 2 of the .NET framework.  If any of the application pools used by SharePoint are set to anything else you will receive an error during the SharePoint 2010 Products and Configuration Wizard.   You can return to IIS manager and review the application pool settings at any time.  If the wizard fails due to the wrong .NET version you can modify the application pool and then restart the wizard.
I would like to hear feedback If you try running SharePoint 2010 on Windows 8 RP for development evaluation purposes.

Thursday, June 6, 2013

SharePoint 2013 Minimal download SharePoint:AjaxDelta

Copyright from: sharepointfordeveloper.blogspot.com

SharePoint 2013 Minimal Download Strategy (MSD) new feature introduced by Microsoft that improving end user experience. I recently check the master page and find some interesting tags that used most at the top of the placeholders.i'e SharePoint:AjaxDelta Tag.




SharePoint:AjaxDelta wrapping all our favorite Delegate Controls and other elements in the Master Page. What this AjaxDelta control does is to only download to the client (browser) what has been changed since the previous download. If nothing has changed, nothing is downloaded Ajax Style.

Following are the AjaxDelta control that are available in the Master page.
  1. DeltaPlaceHolderAdditionalPageHead
  2. DeltaSPWebPartManager
  3. DeltaSuiteLinks
  4. DeltaSuiteBarRight
  5. DeltaSPNavigation
  6. DeltaWebPartAdderUpdatePanelContainer
  7. DeltaWebPartAdderUpdatePanelContainer
  8. DeltaTopNavigation
  9. DeltaSearch
  10. DeltaPlaceHolderPageTitleInTitleArea
  11. DeltaPlaceHolderPageDescription
  12. DeltaPlaceHolderLeftNavBar
  13. DeltaPlaceHolderMain
  14. DeltaFormDigest
  15. DeltaPlaceHolderUtilityContent
when you click on any of the page you will see the start.aspx page  and following by # then your site page URL. example http://xxx/_layouts/15/start.aspx#/SitePages/Home.aspx. The start.aspx page is responsible render the Delta changes control.




The Minimal Download Strategy is by default enabled on Team sites, Community sites but MDS is not enabled on publishing sites. MDS is a web feature.

Thursday, May 9, 2013

Sys.Webforms.PageRequestManagerServerErrorException actual cause


Copyright from: Rama Krishna and Ted Jardine
I finally figured out what is causing the Sys.WebForms.PageRequestManagerServerErrorException. Here are the details of my research:
It's probably a bug in the RoleManagerModule . The issue is that the RoleManagerModule, (which comes into picture when the role manager is enabled in the config) tries to add its cookie to Response's cookie collection. This is done in the EndRequest event of the Application. It should actually do it in the PreSendRequestHeaders event because the PreSendRequestHeaders is the last opportunity to modify the response headers. Under normal circumstances the  PreSendRequestHeaders  gets fired after the EndRequest event, but when Response.Flush is called the sequence may be reversed.
Now, the changes made in AJAX RTM which causes this issue are in PageRequestManager.RenderFormCallback function. When EventValidation is enabled in the page, the function calls Response.Flush (which causes the header to be sent). In this case the Application's EndRequest event is fired after the headers have been sent so an exception occurs in RoleManagerModule when it tries to send the response headers. This eventually leads to the page manager parser exception on the client side because the error response is appended to the actual response sent by the partial update.
There are some possible workarounds:
1. Disable caching of cookies in the RoleManager. For custom modules append cookies in the PreSendRequestHeaders event and not EndRequest event.
2. Handle the Application's Error event to clear the error from the Context selectively.
void Application_Error(object sender, EventArgs e)
{
  //There should be some checking done so that not all the errors
  //are cleared
  Context.ClearError();
}
 3. Disable EventValidation in the web form.
<%@ Page Language="C#" EnableEventValidation="false" %>
  <%@ Page Language="C#" EnableEventValidation="false" %> 
The issue can be repro'ed easily by setting a cookie in the EndRequest event:
void Application_EndRequest(object sender, EventArgs e)
{
  Response.Cookies.Add(new HttpCookie("Test""Test"));
}
And the following simple page will cause the issue:

<%@ Page Language="C#" EnableEventValidation="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
         </div>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:Button ID="Button1" runat="server"  Text="Button" />
                <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
            </ContentTemplate>
        </asp:UpdatePanel>
    </form>
</body>
</html>
4. Writing a new rolemanager that works without any problems
5. Page ValidateRequest="false".
6. Check your firewall settings too. Reference:
7. Page_Load:
Session["FixAJAXSysBug"] = true;

UPDATE: If the problem pages aren't even using session, just turn session off for the page:
<%@ Page EnableSessionState="false" ... %>
Or better yet, set it in your base class to always be off, and turn it on for the pages where you need it on.
8. turn off the keep-alive of our SSL Connection. Reference "How to configure SSL correctly:
http://www.msexchange.org/articles-tutorials/exchange-server-2003/security-message-hygiene/SSL_Enabling_OWA_2003.html

Sunday, April 14, 2013

Code Access Security in ASP.NET 4.0

copyright: www.simple-talk.com


In the third, and final article that introduces Code Access Security in .NET Framework 4.0, Matteo explains, with examples, how the Level2 Security Transparent Model works within a hosted ASP.NET environment.
In previous articles we have seen how the Code Access Security model changed in .NET Framework 4.0.
In What's new in code access security in .NET Framework 4.0 - Part I we saw how the CAS Policy System that was used until .NET Framework 3.5 has now been replaced by the Level2 Security Transparent Model. Permissions to use the protected resources granted to an assembly have been moved from the assembly itself to the host in which the assembly runs. All assemblies in a host now have the same security restrictions, thereby conforming to the Homogeneous Domain concept.
In What's new in code access security in .NET Framework 4.0 - Part II we saw that, despite the Level2 Security Transparent Model being apparently all-or-nothing, it is, in fact, possible to use Allow Partially Trusted Caller Attribute (APTCA) to mix together SecurityTransparentSecurityCritical and SecuritySafeCritical attributes to define granular permissions to grant to an assembly when it need to access protected resources.
In the two previous articles, we have demonstrated how the new CAS technology works, by providing some examples of simple console applications. We said that, in these cases, there is no host to manage, because any simple application will run as an unhosted application, always as full trust code.
In this article we want to analyze how the Level2 Security Transparent Model works within a hosted environment. To do so, we will consider the most important hosted environment that is used today, the ASP.NET Application Domains.
We will start by analyzing how ASP.NET application domains have been modified so as to implement the Level2 Security Transparent Model. We then see how to use configuration files to specify the permissions to grant to assemblies loaded inside these application domains. We will do this with the aid of some examples. Finally, we will see how to use APTCA assemblies in ASP.NET to define, in a more granular way, different permissions for different blocks of code, when more flexibility is required.

ASP.NET 4.0 Application Domain

As described in the MSDN library, an application domain is, “...a construct that hosts use to isolate code running within a process...”
We know that, when a managed application is executed, the .NET runtime is able to create an application domain in which the assemblies are loaded and executed. For security reasons, an application domain is isolated from other application domains, and the assemblies loaded inside it cannot overpass its boundaries.
Prior to .NET Framework 4.0, an ASP.NET application domain’s boundaries would always be executed as full trust. The old CAS Policy System was responsible for granting permissions for each group of code (defined using the code’s evidence) contained inside the application domain and those conditions were verified at the group level. This situation led to a heterogeneous application domain, in which different code groups have different permissions to execute. Because the PermissionSets assigned to each code group was generated from different sources, it was common to see a mixture, or sometimes an overlapping, of permissions.
The .NET Framework 4.0 removes even this behavior by removing the entire CAS Policy System. The new ASP.NET application domain now uses the Level2 Security Transparent Model, and the permissions granted to assemblies inside it are now defined on its boundaries. This makes the application domain a partially trusted environmentand code inside it becomes Security Transparent. Because the permissions defined for the application domain are granted in the same way to all the assemblies inside it, the application domain becomes a homogeneous application domain.

ASP.NET Trust Policies

Despite of what we have said, the default behavior for ASP.NET 4.0 application domain is still to run as full trust environment. To be able to run it as a partially trusted domain we need to set a Trust Policy for it.
ASP.NET 4.0 permits four different Trust LevelsFullHighMedium and Low. While Full (the default value) is used to create a full trusted application domain, the other three generate a partially trusted application domain, giving a set of permissions to it that are defined on the .NET Framework configuration files related to each level.
Configuration files are contained in the Config folder of your .NET Framework 4.0 installation directory (normally C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config). These files are named web_trust.config, where is the desired trust level. The following image shows a screenshot of one of this file, theweb_mediumtrust.config file.
Figure 1: screenshot of the web_mediumtrust.confing configuration file.
If you take a look at it, you will see that the configuration files contain this kind of node:
  1. a set of  xml nodes. They allow you to assign a common name to an assembly. The common name is specified in the Name xml attribute of the node, while the full assembly name is defined in the Description xml attribute. The common name is then used on the rest of the file to refer to it easily.
  2. a <NamedPermissionSets /> xml node. It contains:
  3. a set of <PermissionSet /> xml nodes. Each of them defines a set of permissions that can be applied to an application domain.
  4. a set of  nodes assigned to a specific node. Each of them specifies a single permission granted to the application domain.
A configuration file defines three different PermissionSets:
FullTrust: It contains no permission at all (no  xml nodes are defined). It specifies the directiveUnrestricted=”True”. With it, all the permissions not mentioned on the permission set have full right to be executed. So, if the permission list is empty, the application domain will be a full-trust application domain. All code inside it, unless otherwise specified (as for example, marking the assembly as SecurityTransparent), will run as SecurityCritical.
Nothing: Same as the previous but it doesn’t contain the Unrestricted=”True” attribute. Without it, all the permissions that remain unspecified will have no right to execute. Because the list of permissions is empty, the application cannot execute.
ASP.Net: It represents the default value. It contains a list of all the permissions granted to the application domain. When this value is used, assemblies inside it run as SecurityTransparent code.
At this stage, it could be that you’ll notice something puzzling. It would seem that the following combination:
Trust Level
NamedPermissionSet 
Full
n.a.
Hight
FullTrust
Medium
FullTrust
Low
FullTrust
perform exactly the same things. The application domain is a full trust application domain and the code inside it isSecurityCritical (unless otherwise specified). This is exactly what happens. The explanation as to why this happens is left out by this article due to space limits. To understand it, try to perform a search on the internet about the HostSecurityPolicyResolver class and how it works.
Another thing that can sound strange is the definition of the Nothing PermissionSet. What would be the point of developing an application and then preventing it from executing?
This PermissionSet is useful for administrative purpose. For security reasons, a web server administrator can set the Nothing PermissionSet at the server level, leaving to developers the ability to modify it at the site level. As you will see soon, the trust policies are defined on the web.config file of an ASP.NET application. Administrator can set up the machine’s web.config file with the Nothing trust level, allowing the developer to set its own configuration on the web.config of its application.
Let’s now do some examples. You can find the source code in the supported document section of this article.

A Demo ASP.NET Application

As a demo application, we write a simple dll library, EnvironmentBrowser.dll, that is able to get the list of all the environment variables defined on the machine that hosts the application. We then write an ASP.NET web application that shows the result to the user. We add some useful methods to the web application that are able:
  1. to show the security characteristics of the application domain and
  2. to show the security characteristics of the most interesting (in relation to the goals of the application) methods.
Our EnvironmentBrowser.dll library is made by a single class defined as below:
    public class EnvironmentBrowser
    {
        ///
        /// Get a list of all environment variables defines for the machine
        ///
        ///
        public static string GetEnvironmentVariableList()
        {
         
            IDictionary items =
                Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine);

            StringBuilder sb = new StringBuilder();
            foreach (string x in items.Keys) sb.Append(x + "; ");
            return sb.ToString();
        }
    }

        ///
        /// Get the user name from the environment variables
        ///
        ///
        public static string GetUserName()
        {
            return Environment.GetEnvironmentVariable("USERNAME");
        }
It defines these two methods:
GetEnvironmentVariableList(): It gets all the environment variables defined at the machine level and constructs a string that contains all their names separated by a semicolon.
GetUserName(): It returns the username of the logged user.
Our ASP.NET application is made by only a single page that contains the following code:
        ///
        /// OnLoad Override
        ///
        ///
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            WriteDomainProperties();

            WriteMethodsProperties();

            WriteEnvironmentData();

        }

        ///
        /// Write the domain properties
        ///
        private void WriteDomainProperties()
        {

            AppDomain app = AppDomain.CurrentDomain;

            try
            {
                WriteToPage("Is Homogeous: " + app.IsHomogenous);

                WriteToPage("Is FullTrusted: " + app.IsFullyTrusted);

                WriteToPage("Permisson Set Count: " + app.PermissionSet.Count);

            }
            catch (Exception ex)
            {
                WriteException(ex);
            }

        }

        ///
        /// Write the security property's value of the principal methods.
        ///
        private void WriteMethodsProperties()
        {
            try
            {
                WriteToPage("Method WriteEnvironmentData(): "
                                      + GetMethodProperty (new PageDefault(), "WriteEnvironmentData"));

                WriteToPage("Method GetEnvironmentVariableList(): "
                                     + GetMethodProperty (newEnvironmentBrowser(),"GetEnvironmentVariableList"));

                WriteToPage("Method GetUserName(): "
                                     + GetMethodProperty (new EnvironmentBrowser(),"GetUserName"));
            }
            catch (Exception ex)
            {
                WriteException(ex);
            }

        }

        ///
        /// Write the list of the environment variable defined for the machine
        ///
        public void WriteEnvironmentData()
        {

            try
            {
                WriteToPage("
Environment Variables: "
);

                WriteToPage(EnvironmentBrowser.GetEnvironmentVariableList());
            }
            catch (Exception ex)
            {
                WriteException(ex);
            }

            try
            {
                WriteToPage("
Current User: "
 + EnvironmentBrowser.GetUserName());
            }
            catch (Exception ex)
            {
                WriteException(ex);
            }
        }

        ///
        /// Get the Security Property of a method of an object
        ///
        ///
        private string GetMethodProperty(object obj, string methodName)
        {

            Type t = obj.GetType();

            MethodInfo m = t.GetMethod(methodName);

            if (m.IsSecurityTransparent) return "SecurityTransparent";
            if (m.IsSecuritySafeCritical) return "SecuritySafeCritical";
            if (m.IsSecurityCritical) return "SecurityCritical";

            return String.Empty;
        }

For brevity, we have omitted all the other code not needed by our demo. The ‘code behind’ of the page implements the following methods:
  • WriteDomainProperties():   It writes the security properties of the application domain.
  • WriteMethodsProperties(): It writes the security properties of the main methods of the demo application.
  • WriteEnvironmentData():     It writes the environmental variables list and the username of the user logged to the system.
  • GetMethodProperty():           It gets the value of the security property of a method of an object.

The Full Trust Level

We know that the default trust level for ASP.NET 4.0 is the Full trust level. With it, the application domain is fully trusted, and the code inside it is SecurityCritical.
If we launch our application we get a response like this:
Figure 2: Response of the web application that runs in Full trust level.
The application domain is homogeneous and no permissions are enforced to it. As expected, it runs as full trusted and all the monitored methods run as SecurityCritical code. The application is able to get the list of all the environment variables and display the username of the user logged.

The High Trust Level

Now we move the trust level of the application to the High trust level. To do so, we need to modify the web.config file of the same by adding the following lines:
  <system.web>
    <trust level="High" />
  </system.web>
It states that, when the application domain starts, the web_hightrust.config file must be loaded and the ASP.NetPermissionSet (the default value) must be used.
If we now launch our application, we get the following output:
Figure 3: Response of the web application that runs in High trust level.
With the High trust level, that application domain became partially trusted and all the methods inside it now ran as SecurityTransparent methods. We have sandboxed our application domain.
When the WriteDomainProperties() executes as SecurityTransparent code, it is no more able to get the number of permissions from the PermissionSet property, because its accessor SecurityCritical. An error message is therefore displayed.
Moreover we are still able to have the list of all the environment variables defined on the machine that runs the application. This because the High trust level does not prevent the environment variables to being read. In fact, if you take a look at the web_hightrust.config file you will find the following lines of code:
<IPermission
        class="EnvironmentPermission"
        version="1"
        Unrestricted="true"
       />
The “Unrestricted=”True” attribute that is applied to the EnvironmentPermission states that the code to which the permission applies has full access to the resources protected by the permission.

The Medium Trust Level

If now we change the trust level to Medium in order to see what happens.
  <system.web>
   
    <trust level="Medium" />
  </system.web>
Our output will be:
Figure 4: Response of the web application that runs in Medium trust level.
In this case we are no longer able to get the list of all the environment variables, while the username of the logged user is still accessible.
By inspecting the web_mediumtrust.config file, the directive related to the EnvironmentPermission has changed:
<IPermission
          class="EnvironmentPermission"
          version="1"
          Read="TEMP;TMP;USERNAME;OS;COMPUTERNAME"
        />
The Medium trust level allows the user to be able to read only the variables TEMP, TMP, USERNAME, OS and COMPUTERNAME. So we are able to get the username of the logged user but not the other information.

The Low Trust Level

We now try to use the Low trust level:
<system.web>
   
    <trust level="Low" />
</system.web>
The application will generate the following output:
Figure 5: Response of the web application that runs in Low trust level.
In this case neither the username nor the environment variables became accessible.
If you try to browse the web_lowtrust.config file you will see that it does not mention EnvironmentPermission at all, making it totally unavailable.

Analysis of the Exceptions

As some of you have probably noticed, the exceptions messages seen in the previous paragraph seem strange. We have said that, with a trust level lower than Full, assemblies that execute inside the application domain are marked as SecurityTransparent, but, while the attempt to get the number of permissions granted to the application domain result in a SecurityCritical violation, as expected, the exceptions related to the Environment variables browsing involves the violation of a EnvironmentPermission check. This seems have nothing to do with the SecurityTransparent code attempts to use SecurityCritical code. And this is true. So, what makes this happens ?
We know that the System.Environment class is implemented in the mscorlib.dll assembly of the .NET Framework. If we use Red Gate’s .NET Reflector to inspect the mscorlib.dll, and in particular the methodsEnvironment.GetEnvironmentVariables() and Environment.GetEnvironmentVariable() that are used in ourEnvironmentBrowser class, we see that this two method are implemented as SecuritySafeCritical:
Figure 6: Browsing with the .NET Reflector the Environment.GetEnvironmentVariables() method.
We know that, for what we have said in the WHAT’S NEW IN CODE ACCESS SECURITY IN .NET FRAMEWORK 4.0 – PART II article, this is possible only if the assembly is an assembly marked with APTCA.
With .NET Reflector we see that this is true:
Figure 7: The mscorlib.dll assembly’s attributes list.
The SecurityTransparent method WriteEnvironmentData() calls the two SecuritySafeCritical methodsEnvironment.GetEnvironmentVariables() and Environment.GetEnvironmentVariables(), so no exception occurs.
But when the partially-trusted application domain executes some (SecurityTransparent) code inside it, every security demand generates a stack walk to see if the code has the permission to access some protected resources. If, when the stack walk reaches the application domain boundaries, a security violation is detected, an exception is thrown.
In our demo, the code triggers the demand for the permission to get the environment variables list: When it reaches the application domain boundaries, the exception is thrown if the trust level is lower that High, This explains the exceptions condition that we observe in our demo.

The Conditional APCTA

Suppose that we now want to be able to get the username of the logged-in user, even if we are in Low trust level whilst, at the same time, protecting all the other environment variables. Obviously, the simplest way to do so is to modify the web_lowtrust.confing file to allow it to read the USERNAME environment variable or we can generate our own custom configuration file.
For the purpose of this article we will use a different approach. We have seen that the partially trusted application domain, when a demand is made, starts a stack-walk that reaches the application domain boundaries, and, withLow trust level, an exception occurs. To prevent this behavior, we can perform an Assert on our code in order to stop the stack-walk. As we know, we cannot perform an assert in SecurityTransparent code, so we need to “transform” our GetUserName() method in a SecuritySafeCritical method. This can be done by modifying our EnvironmentBrowser.dll adding to it the APTCA. We do not want to stop here. We want our dll to use the APTCA only in our application but, if another application (or another host in general) tries to use it, it can use the its code as SecurityTransparent. To do so, .NET Framework 4.0 uses the so-called conditional APTCA. This is declared as follow:
[assembly:AllowPartiallyTrustedCallers(PartialTrustVisibilityLevel=PartialTrustVisibilityLevel.NotVisibleByDefault)]
This stated that the APTCA is not visible by default but only to hosts that are setup to use it.
To keep the attribute visible to our web application we need to add the following lines on code in our web.config file:
     <partialTrustVisibleAssemblies>
                <add
                   assemblyName="EnvironmentBrowser"
                    publicKey="00240000048000009400000006020000 ...."
                />
      </partialTrustVisibleAssemblies>
We need to add the EnvironmentBrowser.dll assembly to the partially-trusted visible assemblies list of the application domain that is associated with our application.
You can see from the previous declaration that, in order to add EnvironmentBrowser.dll to such a list, we need not only to specify the assembly name, but even the public key associated with it (for brevity, we have reported only a portion of it being the same a string made by 320 characters). The public key is the one that we used to generate the strong name of the assembly (that is a necessary condition). To get the value for the public key you can use the sn.exe command line in this way:
sn.exe  -Tp
In our case we obtain:
Figure 8: sn.exe output for the EnvironmentBrowser.dll assembly
Now we can modify our GetName() method as follows:
    ///
        /// Get the user name from the environment variables
        ///
        ///
        [SecuritySafeCritical()]
        public static string GetUserName()
        {
           
            EnvironmentPermission permission = new
                     EnvironmentPermission(EnvironmentPermissionAccess.Read, "USERNAME");

            permission.Assert();

            return Environment.GetEnvironmentVariable("USERNAME");
        }
We have marked the method as SecuritySafeCritical and we have created an object of typeEnvironmentPermission. In its constructor we have set the permission to read the USERNAME environment variable. Then we have inserted the call to the Assert method of the object.
The final step is to compile our EnvironmentBrowser.dll library and install it in the Global Assembly Cache (that is a necessary condition).
By running our application we obtain:
Figure 9:  Response of the web application running in Low trust level and using the Conditional-APTCA for the EnvironmentBrowser.dll.
You can see that now the GetUserName() method has become SecuritySafeCritical. The Assert prevents the stack walk reaching the application domain boundaries and, in this way, we are able to get the username of the user logged into the system, as expected.

Conclusion

With this third article about Code Access Security in .NET 4.0, we have completed the review of all the main changes on the CAS system introduces in .NET Framework 4.0. Things changed a lot but, despite of the time needed to learn the new features and how they works, my personal experience has taught me that all the efforts spent will be rewarded when, at the moment to put it on work, things now are really more simple, and less “time, and mind, consuming”.
With these three articles, I hope I was able to assist you to make the transition to the new CAS 4.0 model and to help you to get all the benefits that the new model can bring in your work as a developer.