Tuesday, September 1, 2015

C# / SQL - Performing Distributed Transactions

Distributed Transactions span across multiple processes, which when encapsulated by the distributed transaction manager, will either commit a successful transaction or rollback changes. Distributed Transactions have been available within .NET, since .NET Framework 2.0. The Default Isolation level is set to Serializable, which in usage, creates unnecessary blocking and deadlocks. Therefore, it is suggested you override the default isolation level to ReadCommitted, which reflects the default within SQL Server.
    
/// 
/// This class is responsible for performing Distributed Transactions.
/// 
public class DistributedTransactionUtility
{
    /// 
    /// The Distributed Transaction method which creates a Transaction Scope object 
    ///  and commits if there is no error and rollbacks, incase of exception.
    /// 
    /// 
    ///  The method which performs multiple DB Transactions.
    /// 
    public void DoDistributedTransaction(Action method)
    {
        // Initializes Transaction Scope
        using (var transactionScope = 
            new TransactionScope(TransactionScopeOption.Required, 
            new TransactionOptions { 
                // Default (Isolation Level) : Serializable - Introduces Severe Blocking and Deadlocks
                //  instead use ReadCommitted - Default Transaction Scope for SQL Server.
                IsolationLevel = IsolationLevel.ReadCommitted, 
                Timeout = TransactionManager.DefaultTimeout 
            }))
        {
            try
            {
                // Invokes the Method
                method();

                // Commits the Transaction
                transactionScope.Complete()
            }
            finally
            {
                // Irrespective of success or exception scenario, Transaction Scope must 
                // be disposed explicitly. Dispose method ends the transaction and clears 
                // any data related to it and also clears the scope object.
                transactionScope.Dispose();
            }
        }
    }
}
Invoked using:
new DistributedTransactionUtility().DoDistributedTransaction(() =>
{
    // Multiple - SQL Helper - Methods (ExecuteNonQuery/ExecuteDataset Transactions)
}

Configuration:

  1. Click Start, click Run, type DCOMCNFG and then click OK to open Component Services.
  2. In the console tree, click to expand Component Services, click to expand Computers, click to expand My Computer, click to expand Distributed Transaction Coordinator and then click Local DTC.
  3. Right click Local DTC and click Properties to display the Local DTC Properties dialog box.
  4. Click the Security tab.
  5. Select Security tab of the Local DTC Properties dialog box.
  6. Select Network DTC access checkbox.
  7. In Transaction Manager Communication section check Allow Inbound, Allow Outbound and Mutual Authentication Required options.
  8. Click OK and restart your application.

Saturday, August 8, 2015

ASP.NET MVC / IIS - Optimizing Web Application Performance

Optimizing your web sites in ASP.NET MVC for performance includes cache busting, enabling caching for static resources, enabling gzip compression. To enable caching on static resources, you will need to add the following XML in your web configuration file in the system .webserver element. The control max age parameter determines the length of time to cache the static resources.

 ...
 
  ...
   
   
 

In an effort to compress dynamically generated content (ASP, PHP, ASP.NET) and static files (PDF, JPEG, etc.), you can enable the following settings within your application web configuration. As you use <urlCompression> to define what is compressed, you can use <httpCompression> to define how it is compressed.

      
    
      
      
        
        
        
        
        
      
      
        
        
        
        
        
        
      
    
 

Utilizing Cache Busting can be done to ensure users do not need to clear their browser cache (temporary internet files, etc.) to see changes. Enabling this within the BundleConfig, script and style bundles, when bundles are rendered, will include version numbers. You will want to ensure the following module is added within the web configuration.

 
 

Within your BundleConfig.cs file, you will need to utilize:
BundleTable.EnableOptimizations = true;

Wednesday, April 22, 2015

ASP.NET MVC - Using CDNs (Content Delivery Network)

By utilizing content delivery networks (CDN)s, you will potentially receive several benefits including improved performance, gains from using different domains, pre-cached files, high-capacity infrastructure and distributed data centers. A CDN can distribute the load, save bandwidth, and boost performance. As individual users request static resources such as javascript and stylesheets, browsers limit the number of concurrent connections (or file downloads) to a single domain at a given time, thus allowing users to download additional requests. Additionally, many CDNs provide localized data centers which are closer to the user, and faster to download. For example, if you are browsing your application's site in San Francisco and need to download the javascript or stylesheets, assuming the CDN has a datacenter in California, it would utilize that location to download the file opposed to making the round trip to your local servers (e.g. could be hosted across the country). In terms of pre-caching, if the CDN has been used on a previous site, it is likely the browser used by the individual won't need to re-download the files again.

Approach

In the Bundle Registration (BundleConfig), you will need to enable the use of CDNs. This can be performed by adding the following property on the BundleCollection, at the beginning of the RegisterBundles method. For simplicity, you can set this value to true, but could potentially drive this from the web configuration files.

// Location: BundleConfig.cs
public static void RegisterBundles(BundleCollection bundles)
{
     // Enable CDN Support
     bundles.UseCdn = true;
     ...
}
Once completed, you will need to add the respective CDNs and their local environment fallbacks, within the RegisterBundles method. You should add CDNs for all of the frameworks that have sustainable CDNs, such as jQuery, Bootstrap, Foundation, Kendo, etc. You could host your local files on an internal CDN to your organization, but it would depend on if there is available and hosted infrastructure.

// Location: BundleConfig.cs
public static void RegisterBundles(BundleCollection bundles)
{
     // Enable CDN Support
     bundles.UseCdn = true;
     ...

     // jQuery Bundles
     const string JqueryCdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js";
     bundles.Add(new ScriptBundle("~/bundles/jquery", JqueryCdnPath)
          .Include("~/Scripts/jquery/jquery-{version}.js"));
     ...
     
     // Cache Busting / Optimizations Enabled
     BundleTable.EnableOptimizations = true;
}
With the respective additions of the CDNs, you may need to separate some current bundles, and add to the main layout appropriately.

SharePoint - Moving Sites and Subsites into another Site

If there is a need to move sites and subsites into another site within the same web application, this can be easily performed using the "Site Manager". Often times, this option is over-looked, in favor of site templates, or other backup and restore operations. However, this is the simplest option available.

Note: This site is available on "SharePoint Online or Office 365 Dedicated" as well as any stand-alone SharePoint installation, on the basis that you activate the Publishing Features within SharePoint.

If you visit "http://enter_your_site_url/_layouts/sitemanager.aspx", you'll see the Site Manager, where you can do a move operation of all pages and sub-sites.

  1. Select the parent site of the sub-site you want to move in the left navigation pane.
  2. Check the box next to the sub-site you want to move in the right pane.
  3. Click the Actions drop-down and click Move.
  4. Select Destination of the sub-site selected in the next dialog.
SharePoint Stack Exchange

SharePoint - Feature with ID already exists - Force Option

Occasionally, when deploying SharePoint Solutions (WSP) directly from Visual Studio, you will receive the following error.

Error occurred in deployment step 'Add Solution': A feature with ID {Guid} has already been installed in this farm. Use the force attribute to explicitly re-install the feature.

This error occurs when you have a previously defined feature installed, as part of the same solution, which will trigger the error. To overcome this issue, you can open the feature (double-click) which is part of your actual project, and you will see the properties window come into focus. In this window, you will see details, such as title, description, scope, items in the feature. In the property window, you'll see an option titled 'Always Force Install'. By default, this item is set to "false". If you set this option to "true", it will over-write the feature each time the project is installed.

SharePoint Stack Exchange

Tuesday, March 31, 2015

C# - Performance Counters

Reading performance counters (in C#) require the use of the PerformanceCounter class to read existing predefined or custom counters. The PerformanceCounter class is included in the System.Diagnostic namespace, and provides accessibility to several counters.

The most common counters include Processor, Memory, and Network Utilization.

// CPU Processor Time (in %)
PerformanceCounter cpuCounter = 
    new PerformanceCounter("Processor", "% Processor Time", "_Total");
Console.WriteLine("Current CPU: {0}", cpuCounter.NextValue() +"%");

// Memory Available (in MB)
PerformanceCounter ramCounter = 
    new PerformanceCounter("Memory", "Available MBytes", string.Empty);                        
Console.WriteLine("RAM Available: {0}", ramCounter.NextValue()+"MB");

// Network Utilization (in Bytes/Sec)
PerformanceCounterCategory category = 
    new PerformanceCounterCategory("Network Interface");
String[] instanceName = category.GetInstanceNames();
foreach (string ns in instanceName)
{
    PerformanceCounter netSentCounter = 
        new PerformanceCounter("Network Interface", "Bytes Received/sec", ns);
    PerformanceCounter netRecCounter = 
        new PerformanceCounter("Network Interface", "Bytes Sent/sec", ns);
    Console.WriteLine("Network Interface: {0}", ns);
    Console.WriteLine("Network Usage (Sent): {0}",
        netSentCounter.NextValue()+" Bytes/s");
    Console.WriteLine("Network Usage (Received): {0}",
        netRecCounter.NextValue()+" Bytes/s");
}

Sunday, March 8, 2015

SharePoint - An unexpected error has occurred. (Web Part Page Maintenance)

On occasion, a web part may be causing your SharePoint pages to throw an unexpected error.

An unexpected error has occurred. Web Parts Maintenance Page: If you have permission, you can use this page to temporarily close Web Parts or remove personal settings. For more information, contact your site administrator. Troubleshoot issues with Microsoft SharePoint Foundation.

In addition to leveraging the ULS Logs, to investigate the Correlation ID, you can append "?contents=1" to your page URL. This will allow you to close web parts, restore defaults to web parts, or delete web parts from your page.


Sunday, February 22, 2015

IIS / ASP.NET - Disabling Compatibility Mode/View (Internet Explorer)

In ASP.NET, if you need to disable compatibility view of the end users using your application, you can override the respective browser (Internet Explorer) compatibility mode, by setting the compatibility mode to Edge. By using this setting, the users of the web application, will render using the latest rendering engine available. If in the scenario you don't want to use the latest, you can also define other standards, such as IE8, IE9, etc.

This can be defined in the master page/view using the following meta tag within the <head> section:


   ...
   

Note: The X-UA-Compatible meta tag will need to be the first meta tag, in the circumstance that setting the IE rendering engine to Edge, is not working as intended.

and web.config, by adding a custom header using X-UA-Compatible to the response headers,

  
    
      ...
      
    
  

IIS / ASP.NET - Run all Managed Modules for All Requests (RAMMFAR)

When initially creating an ASP.NET web application, RunAllManagedModulesForAllRequest is enabled by default. If enabled, every request that passes through the ASP.NET pipeline, is treated as a managed modules (or handlers). When all modules are managed, including static content, there are possible performance implications. If you are utilizing a distributed cache provider, such as App Fabric, an implication includes that all managed resources, including static content are passed to the distributed cache (as managed resources), which adds a level of overhead, even if not required. The solution to optimizing your web application, is to disable runAllManagedModulesForAllRequests (RAMMFAR), and add defined locations for your static resources within your web configuration file. The static resources can include but are not limited to CSS, Images, and Scripts.

Firstly, you will want to add location segments for each file/folder location, within the configuration element.

...

   
   
      
         
            
         
      
   
   
   
   
      
         
            
         
      
   
   ...

Once completed, you will see the following section, under system.webServer.
  
     
   
 
You will need to change the value of runAllManagedModulesForAllRequests to false. Also, if you were to stop here, you would potentially get errors from utilizing Bundles within your project, failing upon a Script Render. You will need to ensure you properly add the BundleModule to remediate the errors.
  
     
   
      
      
      
      
      
      
      ...
     
 
Note: In some scenarios, there may be other bundles, that reference static resources that aren't directly accessible in your project. In this scenario, the respective bundle/handler may need to be added to the system.webServer section, similar to the BundleModule. One example, is MiniProfiler, which has resources located at /mini-profiler-resources.

    ...
    
        
        
    

Friday, March 1, 2013

SharePoint – The current operation could not be completed. Try again, or contact your system administrator.

If attempting to utilize Site Manager, to COPY an entire site or any particular pages, and receive the following error.
The current operation could not be completed. Try again, or contact your system administrator. You may re-try the operation, and you may need to clean up the half-created data first before re-trying. If the problem persists, please contact your system administrator.
If you review the logs, and the following is displayed,

System.ArgumentException (0×80070057)
Microsoft.SharePoint.Library.SPRequestInternalClass.GetMetadataForUrl(String bstrUrl, Int32 METADATAFLAGS, Guid& pgListId, Int32& plItemId, Int32& plType, Object& pvarFileOrFolder) at Microsoft.SharePoint.Library.SPRequest.GetMetadataForUrl(String bstrUrl, Int32 METADATAFLAGS, Guid& pgListId, Int32& plItemId, Int32& plType, Object& pvarFileOrFolder) at Microsoft.SharePoint.SPWeb.GetFileOrFolderObject(String strUrl) at Microsoft.SharePoint.Publishing.CommonUtilities.GetFileFromUrl(String url, SPWeb web) at Microsoft.SharePoint.Publishing.PublishingPage.get_Layout() at Microsoft.SharePoint.Publishing.Internal.DeploymentWrapper.cachePageInfoForXmlFiltering(PublishingPage publishingPage) at Microsoft.Office.Server.Utilities.ContentIterator.ProcessItem(SPListItem item, Boolean fIncludeFolderItems, MonitoredScopeWrapper monitoredScopeWrapper, ItemProcessor itemProcessor, ItemProcessorErrorCallout errorCallout) at Microsoft.Office.Server.Utilities.ContentIterator.ProcessItems(SPListItemCollection items, Boolean fIncludeFolderItems, Boolean fIterateInReverseOrder, MonitoredScopeWrapper monitoredScopeWrapper, ItemProcessor itemProcessor, ItemProcessorErrorCallout errorCallout) at Microsoft.Office.Server.Utilities.ContentIterator.<>c__DisplayClassc.<ProcessListItems>b__9(SPListItemCollection items) at Microsoft.Office.Server.Utilities.ContentIterator.ProcessListItems(SPList list, SPQuery query, ItemsProcessor itemsProcessor, ItemsProcessorErrorCallout errorCallout) at Microsoft.Office.Server.Utilities.ContentIterator.ProcessListItems(SPList list, String strQuery, UInt32 rowLimit, Boolean fRecursive, SPFolder folder, ItemsProcessor itemsProcessor, ItemsProcessorErrorCallout errorCallout) at Microsoft.Office.Server.Utilities.ContentIterator.ProcessListItems(SPList list, Boolean fIterateInReverseOrder, ItemProcessor itemProcessor, ItemProcessorErrorCallout errorCallout) at Microsoft.Office.Server.Utilities.ContentIterator.ProcessListItems(SPList list, ItemProcessor itemProcessor, ItemProcessorErrorCallout errorCallout) at Microsoft.SharePoint.Publishing.PublishingWeb.IterateOverAllPages(ProcessPublishingPage callToProcessPublishingPage) at Microsoft.SharePoint.Publishing.Internal.DeploymentWrapper.configureExportCopyOrMove(String[] sourceSmtObjectIds, SPExportSettings& exportSettings, SPIncludeVersions versionsToInclude) at Microsoft.SharePoint.Publishing.Internal.DeploymentWrapper.Copy(String[] sourceSmtObjectIds, String destSmtObjectId) at Microsoft.SharePoint.Publishing.Internal.WebControls.CopyObjects.Copy() at Microsoft.SharePoint.Publishing.Internal.WebControls.CopyObjects.DoWork() at Microsoft.Office.Server.Diagnostics.FirstChanceHandler.ExceptionFilter(Boolean fRethrowException, TryBlock tryBlock, FilterBlock filter, CatchBlock catchBlock, FinallyBlock finallyBlock

You’ll want to check the pages contained in the page library, and download and view them in a text editor. Once completed, you will want to make sure the PublishingPageLayout is correctly matching your source web application, and when it’s corrected, re-upload the pages and you’ll be able to perform the copy operation.


SharePoint – Web Service Requests in InfoPath Forms (Classic to Claims)

Without writing code, you can populate User Profile Service (UPS) information into your fields in InfoPath forms. This process is clearly defined in the following blog. However, as this works perfectly, in the classic-based authentication there are several modifications that will need to be made, to fully utilize the forms, as a result of product limitations caused by Claims-based authentication.

Firstly, a Secure Store ID will need to be created in Central Administration (Manage Service Applications), you’ll need to assign the Target Application ID, and add the Target Application Administrators which would ideally need to be a generic ID that never expires, and the members that are mapped to the credentials defined. You’d need to then set the credentials on that domain account for the secure store target application. Lastly, under Central Administration (General Application Settings), and InfoPath Forms Services, the option to ‘Allow user form templates to use authentication information contained in data connection files’ is selected.

To re-mediate any issues with the data connections previously created while in classic (that utilize web services), you will need to download the previously created data connections from their respective data connection libraries, and open them using any text editor. You’ll notice that the UDCX files, are purely XML. Modify the XML, such that the following information is included. What this allows, is for impersonation to allow the user accounts accessing this form, to be able to get the correct data from the web services.

    
 
Once this change is made, simply re-upload and publish your data connection file, into the data connection library associated with your InfoPath Form Library. Once you complete this action then re-open your InfoPath Form template. If you were providing information on a button press, form load, or form submit operation, you’d simply modify your existing actions to include the following details. You would need to add another action to set a field’s value, and when the dialog appears, select the drill-down beside the field textbox.


Within the next dialog, click the drop-down and select your respective web service. In the image below, the data connection was named GetUserProfileByName, and you will need to select the field AccountName and press OK.


and in the value field, simply enter userName(), or add it by the function entry under Users.

Lastly, you’ll need to perform a query using a data connection action, utilizing the data connection associated with the web service request. These two major items need to be before your other field-based actions as it’ll then associate the requests with your ID, and populate your information correctly.

Below is a sample image, which illustrates what the actions should look like, in the correct order, to acquire the First Name of the user. These field values for the individual user profile service attributes, is listed in the blog article talked about above.


Tuesday, February 26, 2013

SQL – Locked in Single-User Mode

If you ever want to see what sessions are active in SQL, or if you ever perform a SharePoint Backup through Central Administration, and SQL Server goes into single-user mode and does not remove that state – the following SQL query will return all active user sessions, by ID.

select d.name, d.dbid, spid, login_time, nt_domain, nt_username, loginame
from sysprocesses p inner join sysdatabases d on p.dbid = d.dbid
where d.name = 'db_name'
GO
Once you get this ID, you can just manually kill the session, to the ID, and then disable single-user mode in the respective tables, etc.

Friday, November 9, 2012

SharePoint 2010 - Remove / Disable Themes

If you've ever encountered the need the disable themes on a site collection, there are a few options you may have available.

Firstly, there are policies in Central Administration to remove the ability to change the themes across the entire web application, which can be done by the following:
  1. Visit Central Administration > Application Management > Web Applications > Manage Web Applications.
  2. Select the Web Application that you want to restrict the themes on.
  3. Click on "Permission Policy Level" on the Ribbon.
  4. Name the policy, and find the permission "Apply Themes and Borders" and toggle the "Deny" check box.
  5. Click save.
  6. Click on "User Policy" on the Ribbon.
  7. Add the users and groups you want to restrict, and then apply the policy you just created.

Alternatively, if you want to manually remove the themes, you can update the theme entries, in a file called:
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\Template\Layouts\1033\SPTHEME.XML

There, you can remove all themes with the exception of default - the sections you would want to delete are the nodes. Noted, I take no responsibility for any issues caused by this method. I would expect you to make a backup of this file.

If you can't do either of the above options, and utilizing a managed environment. You could take a third approach, which involves removing the available themes, resetting your themes to default, and disabling the 'Enhanced Theming' hidden feature. You can remove all the managed themes, via the following code in a site-scoped feature receiver, on feature activation.

if (properties != null)
{
     using (SPSite _SPSite = properties.Feature.Parent as SPSite)
     {
         using (SPWeb web = _SPSite.RootWeb)
         {
             ReadOnlyCollection ManagedThemes = null;
             ManagedThemes = ThmxTheme.GetManagedThemes(web.Site);
             SPFile file = null;
             foreach (ThmxTheme themes in ManagedThemes)
             {
                 file = web.GetFile(themes.ServerRelativeUrl);
                 file.Delete();
             }
         }
     }
 }
and then also disabled the following feature through feature stapling,

'Enhanced Theming' - GUID: 068bc832-4951-11dc-8314-0800200c9a66
Also, to reset your theme, in some site scoped feature stapler, you could also reset the theme to default.
ThmxTheme.RemoveThemeFromWeb(_SPWeb, false);

Thursday, September 27, 2012

SharePoint 2010 - Cannot access the local farm.

Issue:

If you're encountering the following error, when trying to run a powershell script, you may not have sufficient permissions on the database.

Get-SPWeb : Cannot access the local farm. Verify that the local farm is properly configured, currently available, and that you have the appropriate permission to access the database before trying again.

The issue can be remedied with a few quick powershell commands.

Workaround:

Perform the following script in the SharePoint Management Shell, as a farm administrator and it will remove the error.
Get-SPDatabase | Add-SPShellAdmin SomeDomain\SomeUserName
This will grant the user both access to the configuration database as well as the content database. Alternatively, you can revoke that granted access with the opposite command.
Get-SPDatabase | Remove-SPShellAdmin SomeDomain\SomeUserName