Jeff Widmer's Blog

ASP.NET, ASP.NET MVC, C#, VB.NET, IIS7, Windows Forms, VB6, ASP 3.0

  • How to troubleshoot a SharePoint 2010 error

    When an error occurs within Microsoft SharePoint Foundation 2010 a Correlation ID will be displayed in the error message:

    image

    This Correlation ID is logged within the SharePoint log files and you can use it to find out more details about the error that occurred. 

    The two pieces of information you will need from the error message above are the Correlation ID and the date and time of the error. 

    Once you have those two pieces of information, browse to the SharePoint log files on your SharePoint server located at:

    C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\LOGS

    The log files will be labeled with a date time stamp so find the one that corresponds to the time frame of the error and then open this log file in Notepad (or the text editor of your choice) and search for the Correlation ID. 

    You will probably find it listed in several places, from the beginning GET request to when the error occurred, and finally to when the logging of correlation data stops.  Of course you are probably most interested in the error message but there will be more information in the log associated with the Correlation ID to help you find the root cause of the error.

  • How to switch between HTTP and HTTPS in ASP.NET MVC2

    ASP.NET MVC2 has the new RequireHttpsAttribute that you can use to decorate any action to force any non-secure request to come through HTTPS (SSL).  It can be used as simply as this:

            [RequireHttps]
            public ActionResult LogOn()
            {
            .....
            }

    Now any request to the LogOn action that is not over HTTPS will automatically be redirected back to itself over HTTPS.  This is very useful and easy to implement.

    Unfortunately though, once the scheme is changed to HTTPS, all following requests will also be under HTTPS, which is not necessarily what you want.  In most cases you do not need all requests to your site to be secure but only certain ones such as the logon page or pages that accept credit card information. 

    To handle this you can override the Controller.OnAuthorization method.  From within this method, you can check to see if the RequireHttps attribute is set on the Controller Action by searching the Attributes collection of the ActionDescriptor object. If the RequireHttpsAttribute is not set AND the request is under SSL, then return a redirect result to the HTTP (non-SSL) url:

    public class ControllerBase : Controller
    {

    protected override void OnAuthorization(AuthorizationContext filterContext)

      //the RequireHttpsAttribute set on the Controller Action will handle redirecting to Https. 
      // We just need to handle any requests that are already under SSL but should not be. 
      if (Request.IsSecureConnection) 
       {
        Boolean requireHttps = false;
        requireHttps = filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), false).Count() >= 1; 


        //If this request is under ssl but yet the controller action
        // does not require it, then redirect to the http version.
        if (!requireHttps && !filterContext.IsChildAction)
        {
            UriBuilder uriBuilder = new UriBuilder(Request.Url);

            //change the scheme
            uriBuilder.Scheme = "http";
            uriBuilder.Port = 80;

            filterContext.Result = this.Redirect(uriBuilder.Uri.AbsoluteUri);
        }
       }

        base.OnAuthorization(filterContext);
    }

    }

    Now any HTTPS requests to controller actions that are not decorated with a RequireHttps attribute will be forced back to an HTTP (non-secure) request.

    EDITED (2010-08-21): Modified the code as recommended by the comment from Donnie Hale to move the check for Request.SecureConnection to the outermost if block.

    EDITED (2011-01-06): Modified the code as recommended by the comment from Sergio Tai to not perform this check if use Html.Action in views

  • SharePoint 2010 - The Security Token Service is not available

    I am in the process of setting up a SharePoint Foundation 2010 machine.  After installing SharePoint Foundation 2010 I noticed a warning in the Central Admin > Review problems and solutions report that the Security Token Service is not available.

    image

    The Security Token Service is not available.
    The Security Token Service is not issuing tokens. The service could be malfunctioning or in a bad state.
    SPSecurityTokenService (SecurityTokenService)

    The problem ended up being that the default configuration of the IIS Application Pools were set to 32-bit:

    image

    When SharePoint was installed all of the application pool accounts were added with 32-Bit enabled which prevented the SharePoint application pools from starting.  I had corrected this for the Central Admin site and also the root SharePoint site but the application pools for the Security Token Service were still set to use the 32-Bit application which was preventing the service from starting.

    Changing this setting in each of the application pools (there were several created so check them all) fixed the issue and then the warning went away.

  • Configuring Incoming Email for SharePoint 2010 Foundations

    SharePoint sites can receive email and store incoming messages in lists.  This allows a user to send an email to a particular email address and have the contents of the email show up in a SharePoint list.  You can also email enable a calendar in SharePoint 2010 Foundations and then connect that calendar to Outlook to create a shared calendar for all of your users.  Below are instructions on how to enable incoming email in SharePoint 2010 Foundations.

    There are three places you will need to modify to get incoming email to show up in SharePoint lists and calendars.  The first is in the SharePoint Central Administration, the second is within the IIS 6.0 Manager (for the SMTP settings), and the third is enabling it in the list itself.

    Step 1 - SharePoint Central Administration

    Go to SharePoint Central Administration on your SharePoint server and then browse to System Settings > Configure incoming e-mail settings:

    image

    Within the Configure incoming e-mail settings page you will need to select the “enable sites on this server to receive e-mail” option and then set the domain name of the e-mail server:

    image

     

    Step 2 - IIS 6.0 Manager for SMTP configuration

    You will now use the IIS 6.0 Manager to add the domain name you are using to send mail to the email enabled lists to this server (so that it will accept email to this domain name).

    Go to Administrative Tools > Internet Information Services (IIS) 6.0 Manager

    image

    In the IIS6 MMC expand the local server and then expand the SMTP Virtual Server.  You now need to add the domain name specified in the Central Admin configuration settings to the domains that will receive email on this SMTP Server.

    Right click Domains and then choose New > Domain…

    image

    Choose the Alias option and then click Next

    image

    Then add the domain name where users will send email as an alias for the SMTP server.  Note: Of course make sure the DNS MX records are set to point this domain name to the IP address of this server.  Note2: Also make sure port 25 is open to your server so it can receive email.

    image

     

    Step 3 – Enabling incoming email in the SharePoint list

    The final step is to enable incoming email on the lists that you want to accept email and also specify an email address for the list.

    To do this, browse to the List Settings of the List:

    image

    Then on the right-hand side will be the Communications section with the Incoming e-mail settings link.

    image

    Click this link to bring up the Incoming E-mail Settings dialog for this list.  Choose Yes to enable the list to receive email and then enter an email address for this list.  (There are also other options to set to control what content from the email is added to the list and the permissions.)  Click OK to save your settings.

    image

    Now you can send an email to this list email address (in the example above it would be mylist@sharepoint.mycompany.com) and the contents of the email will be automatically added to the discussion list.

     

  • How to implement ISNULL(SUM(ColumnName),0) in Linq2SQL

    I had a Linq2Sql statement like this:

    var q = from o in db.OrderItem
                      where o.UserId == UserId
                      select o.Amount;

    And then I was trying to get the sum of the OrderItem.Amount column by doing this:

    total = q.Sum();

    This worked fine as long as there were rows for this UserId in the OrderItem table.  But if there are no rows in the table for this UserId I was getting this exception:

    System.InvalidOperationException: The null value cannot be assigned to a member with type System.Decimal which is a non-nullable value type.

    Linq2Sql was creating the following SQL query:

    SELECT SUM([t0].[Amount]) AS [value]
    FROM [dbo].[OrderItem] AS [t0]
    WHERE [t0].[UserId] = @p0

    which is fine but I really want this:

    SELECT ISNULL(SUM([t0].[Amount]),0) AS [value]
    FROM [dbo].[OrderItem] AS [t0]
    WHERE [t0].[UserId] = @p0

    Notice the ISNULL in the statement above that will return 0 if there are no rows found for this UserId.

    Eventually I was able to track it down to var q being an IQueryable in the Linq2Sql statement above.  By using ToArray() like this:

    var q = (from o in db.OrderItem
                      where o.UserId == UserId
                      select o.Amount).ToArray();
    total = q.Sum();

    var q is now an IEnumerable (because ToArray() returns an IEnumerable<Decimal>).  And instead of IQueryable.Sum() trying to apply an expression to the Null value,   IEnumerable.Sum() will just loop through all of the items in the array and sum the values.  In this case there are no items in the array so 0 is returned. 

    I could have also explicitly declared q as an IEnumerable<Decimal>:

    IEnumerable<Decimal> q = from o in db.OrderItem
                      where o.UserId == UserId
                      select o.Amount;
    total = q.Sum();

    Just to note, the SQL statement is still not using ISNULL() but I am getting the result I want from within C#.

     

    UPDATE (2010-07-22):  Another solution from RichardD:

    var q = from o in db.OrderItem 
              where o.UserId == UserId 
              select o.Amount;
    Decimal total = q.Sum(a => (Decimal?)a) ?? 0M;
     

    OR 

    IQueryable<Decimal?> q = from o in db.OrderItem
                      where o.UserId == UserId
                      select (Decimal?)o.Amount;
    Decimal total = q.Sum() ?? 0;
     

     

     

  • New Home Improvement StackExchange site coming soon

    I am really excited about the new Home Improvement StackExchange site that is coming up on its beta release.  This is a new site based off of the very popular StackOverflow site that will be targeted toward home improvement for contractors and (serious) DIY'ers. When I am not programming I am working on my house in some way so I am looking forward to learning a lot from other users but also maybe being able to help some people out.

    If you haven’t seen the StackExchange Area 51 you should go check it out too.  StackExchange was put together about 6 months ago as a way for people to pay for their own Question and Answer site just like StackOverflow.  But a lot of the started StackExchange sites became stagnant.  So Area 51 was developed to let people propose new sites they would like and then only allow them to be created when enough people have committed to the site.

    Currently the Home Improvement site is in the commitment phase (up to 74% complete).  As soon as enough people have committed to it to hit 100% then it will start the private beta and then the public beta.  If you commit to the site, then you get to be part of the private beta.

    So if you are interested in an awesome Home Improvement site just like StackOverflow then head over to the Area 51 Home Improvement proposal and commit to it.

  • SharePoint 2010 – SQL Server has an unsupported version 10.0.2531.0

    I am trying to perform a database attach upgrade to SharePoint Foundation 2010.

    At this point I am trying to attach the content database to a Web application by using Windows Powershell:

    Mount-SPContentDatabase -Name <DatabaseName> -DatabaseServer <ServerName> -WebApplication <URL> [-Updateuserexperience]

    I am following the directions from this TechNet article: Attach databases and upgrade to SharePoint Foundation 2010.  When I go to mount the content database I am receiving this error:

    Mount-SPContentDatabase : Could not connect to [DATABASE_SERVER] using integrated security: SQL server at [DATABASE_SERVER] has an unsupported version 10.0.2531.0. Please refer to “http://go.microsoft.com/fwlink/?LinkId=165761” for information on the minimum required SQL Server versions and how to download them.

    At first this did not make sense because the default SharePoint Foundation 2010 website was running just fine.  But then I realized that the default SharePoint Foundation site runs off of SQL Server Express and that I had just installed SQL Server Web Edition (since the database is greater than 4GB) and restored the database to this version of SQL Server.

    Checking the documentation link above I see that SharePoint Server 2010 requires a 64-bit edition of SQL Server with the minimum required SQL Server versions as follows:

  • SQL Server 2008 Express Edition Service Pack 1, version number 10.0.2531
  • SQL Server 2005 Service Pack 3 cumulative update package 3, version number 9.00.4220.00
  • SQL Server 2008 Service Pack 1 cumulative update package 2, version number 10.00.2714.00

    The version of SQL Server 2008 Web Edition with Service Pack 1 (the version I installed on this machine) is 10.0.2531.0.

    SELECT @@VERSION:
    Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (X64)   Mar 29 2009 10:11:52   Copyright (c) 1988-2008 Microsoft Corporation  Web Edition (64-bit) on Windows NT 6.1 <X64> (Build 7600: ) (VM)

    But I had to read the article several times since the minimum version number for SQL Server Express is 10.0.2531.0.  At first I thought I was good with the version of SQL Server 2008 Web that I had installed, also 10.0.2531.0.  But then I read further to see that there is a cumulative update (hotfix) for SQL Server 2008 SP1 (NOT the Express edition) that is required for SharePoint 2010 and will bump the version number to 10.0.2714.00.

    So the solution was to install the Cumulative update package 2 for SQL Server 2008 Service Pack 1 on my SQL Server 2008 Web Edition to allow SharePoint 2010 to work with SQL Server 2008 (other than the SQL Server 2008 Express version).

    SELECT @@VERSION (After installing Cumulative update package 2):
    Microsoft SQL Server 2008 (SP1) - 10.0.2714.0 (X64)   May 14 2009 16:08:52   Copyright (c) 1988-2008 Microsoft Corporation  Web Edition (64-bit) on Windows NT 6.1 <X64> (Build 7600: ) (VM)

  • SQL Server 2008 Service Pack 1 and the Invoke or BeginInvoke cannot be called error message

    When trying to install SQL Server 2008 Service Pack 1 to a SQL Server 2008 instance that is running on a virtual machine, the installer will start:

    image 

    But then after about 20 seconds I receive the following error message:

    image

    TITLE: SQL Server Setup failure.
    -----------------------------
    SQL Server Setup has encountered the following error:
    Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
    ------------------------------
    BUTTONS:
    OK
    ------------------------------

    Searching for this issue I found that several people have the same problem and there is no clear solution.  Some had success with closing windows or Internet Explorer but that didn’t work for me; what did work is to make sure the SQL Server 2008 “Please wait while SQL Server 2008 Setup processes the current operation.” dialog is selected and has the focus when it first shows up.  Selected (with the current focus) it looks like this:

    image 

    Without focus the dialog looks like this:

    image

    Add a comment if you find out any information about how to consistently get around this issue or why it is happening in the first place.