Visual Studio 2010 SharePoint Power Tools allow sandboxed Visual Web Parts

by fkollmann 6/18/2010 9:07:41 PM

Visual Web Parts are now possible even with sandboxed solutions as Microsoft released the Visual Studio 2010 SharePoint Power Tools.

HOMEPAGE

My favorite Visual Studio 2010 Tips

by fkollmann 6/18/2010 8:35:56 PM

My favorite tips from Sara Ford's 101 Visual Studio Tips which were all new to me and I tested all of them:

Tip 2: Cycle trough the clipboard stack when pasting text by pressing Ctrl + Shift + V . This allows to past more than just the latest copied text.

Tip 8: Ctrl + , (comma) allows to get a simple type search view (like in Eclipse).

Tip 19+20: Ctrl + Alt + <arrow key> to do block select (like in the command prompt). When starting to type it allows to edit multiple lines.

Tip 37: Ctrl + F3 to search for the currently selected word.

Tip 88: Ctrl + . (dot) opens the small menu e.g. when renamed a method or variable name. No longer trying to catch that one with the mouse cursor :) .

Tip 96: Visualizer for event sender parameter in WPF.

More tips: http://blogs.msdn.com/b/saraford/archive/2010/03/30/speaking-at-devdays-2010-in-the-netherlands-visual-studio-tips.aspx

SharePoint 2010 resource files have to be complete

by fkollmann 6/17/2010 12:29:00 PM

After trying a lot of stuff on how to translate/localize XML declarations and code in SharePoint 2010, I came across a bad topic: translated resource files have to be complete!

Assuming that the following structure exists:

  • Foo.resx
    • HelloWorld –> “Hello World!”
    • ExampleTitle –> “Example”
  • Foo.de-DE.resx
    • HelloWorld –> “Hallo Welt!”

Requesting ‘ExampleTitle’ in a German web will not return the expected “Example” (as it would using compiled resources) but “$Resources:Example”.

There are two ways how resources are being requested by SharePoint:

Requesting localized string by XML declaration

These are the resource references: $Resources:<resx file base name>,<resx key>;

This results in the following error in the SharePoint log:

06/15/2010 16:57:20.06     vssphost4.exe (0x0F98)                      0x06C8    SharePoint Foundation             General                           8e25    Medium      Failed to look up string with key "<resx key>", keyfile <resx file>.    
06/15/2010 16:57:20.06     vssphost4.exe (0x0F98)                      0x06C8    SharePoint Foundation             General                           8l3c    Medium      Localized resource for token '<resx key>' could not be found for file with path: "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\Template\Features\<feature name>\feature.xml".    

Requesting localized string using code

I use the following method to query translations from code:

UPDATE: Due to the fact that the SPContext is not set in feature receivers when the feature is being activated using the commandline, I extended the function to be able to pass ((SPSite)properties.Feature.Parent).RootWeb:

public static class LocalizationHelpers
{
    public const string DefaultResourceFile = "<default resource name, without extension>";

    public static string GetLocalizedString(string str)
    {
        if (string.IsNullOrEmpty(str))
            throw new ArgumentException("null or empty", "str");

        return GetLocalizedStringInternal(str, DefaultResourceFile, null);
    }

    public static string GetLocalizedString(string str, SPWeb web)
    {
        if (string.IsNullOrEmpty(str))
            throw new ArgumentException("null or empty", "str");

        if (web == null)
            throw new ArgumentNullException("web");

        return GetLocalizedStringInternal(str, DefaultResourceFile, web);
    }

    public static string GetLocalizedString(string str, string file)
    {
        if (string.IsNullOrEmpty(str))
            throw new ArgumentException("null or empty", "str");

        if (string.IsNullOrEmpty(file))
            throw new ArgumentException("null or empty", "file");

        return GetLocalizedStringInternal(str, file, null);
    }

    public static string GetLocalizedString(string str, string file, SPWeb web)
    {
        if (string.IsNullOrEmpty(str))
            throw new ArgumentException("null or empty", "str");

        if (string.IsNullOrEmpty(file))
            throw new ArgumentException("null or empty", "file");

        if (web == null)
            throw new ArgumentNullException("web");

        return GetLocalizedStringInternal(str, file, web);
    }

    private static string GetLocalizedStringInternal(string str, string file, SPWeb web)
    {
        // determine language
        var lang = 1033u; // english

        if (web != null)
            lang = web.Language;

        else if ((SPContext.Current != null) && (SPContext.Current.Web != null))
            lang = SPContext.Current.Web.Language;

        // request string
        var r = SPUtility.GetLocalizedString("$Resources:" + str, file, lang);
        // enrich error string
        if (r.StartsWith("$Resources:"))
            r = string.Format("$Resources:{0},{1},{2};", file, str, lang);

        return r;
    }
}

More details: http://blogs.msdn.com/b/johnwpowell/archive/2009/11/29/sharepoint-2010-localization-with-visual-studio-2010.aspx

SharePoint 2010 ListTemplate.Name cannot be translated

by fkollmann 6/16/2010 5:35:50 PM

The whole day I was hunting an error where SharePoint 2010 refused to create a list instance (both by XML declaration and by code). All I got was either “filename invalid … 0x81020030” (XMl declaration) or NullReferenceException (by code, having the other error as inner exception when debugging).

After digging around a little bit I came across the following log message:

06/16/2010 17:24:12.65     vssphost4.exe (0x1290)                      0x17D4    SharePoint Foundation             General                           72k9    High        Failed to retrieve the list schema for feature fb18e164-124b-4da0-96d0-a6404af4996c, list template 17346; expected to find it at: "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\Template\Features\Common_ListNavigation\$Resources:common,ListNavigationListName;".   

Since I try to define constants in resource files, too. I simply stored the ListTemplate.Name attribute in a resource to ensure the name does not have to be changed in different places:

<ListTemplate
    Name="$Resources:common,ListNavigationListName;"
    Type="17346"
    BaseType="0"
    OnQuickLaunch="TRUE"
    SecurityBits="11"
    Sequence="410"
    DisplayName="ListNavigationListDefinition"
    Description="My List Definition"
    Image="/_layouts/images/itgen.png"/>

Unfortunately this is not supported :-/ .

C++ 0x features in Visual Studio

by fkollmann 4/7/2010 8:17:11 AM

Stephan T. Lavavej published a list of the C++ 0x features being implemented into Visual Studio 2008 and Visual Studio 2010. It’s a nice overview to see the current implementation status:

 

C++0x Core Language Features

Proposal

VC9

VC10

Rvalue references

N2118

No

v2

    Rvalue references v2

N2844

No

v2

    Rvalue references for *this

N2439

No

No

    Initialization of class objects by rvalues

N1610

Yes

Yes

static_assert

N1720

No

Yes

auto

N1984

No

Yes

    Multi-declarator auto

N1737

No

Yes

    Removing old auto

N2546

No

Yes

    Trailing return types

N2541

No

Yes

Lambdas

N2927

No

v1.0

decltype

N2343

No

Yes

Right angle brackets

N1757

Yes

Yes

Extern templates

N1987

Yes

Yes

nullptr

N2431

No

Yes

Strongly typed enums

N2347

Partial

Partial

Forward declared enums

N2764

Partial

Partial

Extended friend declarations

N1791

Partial

Partial

Local and unnamed types as template arguments

N2657

Yes

Yes

C++0x Core Language Features: Concurrency

     

exception_ptr

N2179

No

Yes

Thread-local storage

N2659

Partial

Partial

C++0x Core Language Features: C99

     

__func__

N2340

Partial

Partial

C99 preprocessor

N1653

Partial

Partial

long long

N1811

Yes

Yes

 

Q: http://blogs.msdn.com/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx

Generating time-based/type 1 GUIDs

by fkollmann 3/31/2010 5:25:10 PM

Unfortunately I have been unable to find any implementation for time-based GUIDs (or “type 1” to call them correctly). Usually they are not used that often today since the random generated once are quite as good (see .NET System.Guid implementation).

However since I have been doing some testing with the Apache Cassandra “NoSQL” database I needed an implementation for .NET. This is mainly because data is sorted on write (one of the big differences to RDBS) by it’s key name AND only by it’s key name. This means if you have a distributed system writing in a database and you need a time based sorting which is globally unique, then time-based GUIDs are your choice.

I did the following implementation and ran some test cases on it. It should be fine (esp. since this is not the first time I implement them):

namespace System
{
    /// <summary>
    /// helper class to create "type 1"/time based GUIDs.
    ///
    /// see
http://de.wikipedia.org/wiki/Universally_Unique_Identifier
    /// see http://tools.ietf.org/html/rfc4122
    /// </summary>
    public static class TimeGuid
    {
        public static Guid New()
        {
            var id = new byte[16];

            // set timestamp and version
            var ts = GetNextCurrentTimestamp();

            id[0] = (byte)(ts & 0xff);
            id[1] = (byte)((ts >> 8) & 0xff);
            id[2] = (byte)((ts >> 16) & 0xff);
            id[3] = (byte)((ts >> 24) & 0xff);

            id[4] = (byte)((ts >> 32) & 0xff);
            id[5] = (byte)((ts >> 40) & 0xff);

            id[6] = (byte)((ts >> 48) & 0xff);
            id[7] = (byte)(((ts >> 56) & 0x0f) | 0x10 /* version number: 1 */);

            // set clock sequence
            var clock = _clockSequence;

            id[8] = (byte)(((clock >> 8) & 0x03) | 0x08);   // force two highest bits to be "10"
            id[9] = (byte)(clock & 0xff);

            // set mac address/node id
            var nodeId = _nodeId;

            if (nodeId.Length < 6)
                throw new NotSupportedException("node id is too short; no network card found?");

            id[10] = nodeId[0];
            id[11] = nodeId[1];
            id[12] = nodeId[2];
            id[13] = nodeId[3];
            id[14] = nodeId[4];
            id[15] = nodeId[5];

            return new Guid(id);
        }

        private static readonly short _clockSequence = 0;
        private static readonly long _timeStampBase;
        private static readonly byte[] _nodeId;
        private static long _lastTimeStamp;

        /// <summary>
        /// contains the error occurred when trying to
        /// determine the node id.
        ///
        /// consider this is a warning, there is a fallback.
        /// this field containing an error does not lead
        /// to invalid GUIDs
        /// </summary>
        public static Exception NodeIdError
        {
            get; private set;
        }

        static TimeGuid()
        {
            // create base timestamp; in .NET ticks are 100ns
            // which conforms the GUID standard
            _timeStampBase = new DateTime(1582, 10, 15, 0, 0, 0, 0, DateTimeKind.Utc).Ticks;

            // initialize current timestamp
            _lastTimeStamp = (DateTime.UtcNow.Ticks - _timeStampBase);

            // initialize clock sequence with a random value
            var rg = new Random(DateTime.Now.Millisecond);
            var rnd = Guid.NewGuid().ToByteArray();

            _clockSequence = (short)(
                (ushort)rnd[rg.Next(0, 15)] |
                ((ushort)rnd[rg.Next(0, 15)] << 0xff)
                );

            // gather node id
            _nodeId = GetNodeId();
        }

        private static long GetNextCurrentTimestamp()
        {
            var cts = (DateTime.UtcNow.Ticks - _timeStampBase);
            var lts = Interlocked.Read(ref _lastTimeStamp);

            // update last timestamp because it's outdated
            if (cts > lts)
            {
                if (Interlocked.CompareExchange(ref _lastTimeStamp, cts, lts) == lts)
                    return cts;

                // the last timestamp was already updated
                // so this means it's now up to date...
                // simply rely on its safe value!
                return Interlocked.Increment(ref _lastTimeStamp);
            }

            // the last timestamp is newer or
            // yet unchanged; rely on its safe value!
            return Interlocked.Increment(ref _lastTimeStamp);
        }

        private static byte[] GetNodeId()
        {
            try
            {
                // gather all network interfaces
                var nics = NetworkInterface.GetAllNetworkInterfaces();

                foreach (var n in nics)
                {
                    // check if a network interface has
                    // a mac address which is long enough
                    // (older devices have 6 bytes which is
                    // sufficient for GUIDs)
                    var mac = n.GetPhysicalAddress();

                    var macAddr = mac.GetAddressBytes();

                    if (macAddr.Length >= 6)
                        return macAddr;
                }
            }
            catch (Exception x)
            {
                NodeIdError = x;

                return Guid.NewGuid().ToByteArray();
            }

            // not supported or no network card found?
            NodeIdError = new Exception("no network card found");

            return Guid.NewGuid().ToByteArray();
        }
    }
}

Feel free to use the code like you want. If you find errors or good points for improvement, please let me know.

Remote IP in WCF 3.5

by fkollmann 10/9/2009 4:22:21 PM

Keyvan Nayyeri wrote a blog post a while ago about how to gather the remote IP from remote WCF connections. I wrote an extension method based on his code:

public static RemoteEndpointMessageProperty GetRemoteEndpoint(this OperationContext oc)
{
    if (oc == null)
        throw new NullReferenceException();

    object v;

    if (!oc.IncomingMessageProperties.TryGetValue(RemoteEndpointMessageProperty.Name, out v))
        return null;

    return v as RemoteEndpointMessageProperty;
}

Unfortunately it does not seem to work with the WCF implementation of Silverlight 3 :( .

Q: http://nayyeri.net/detect-client-ip-in-wcf-3-5

UPDATE: Switched to TryGetValue()

TFS 2010 “Basic” Edition

by fkollmann 10/6/2009 10:09:00 AM

There is going to be a “Basic” Edition of TFS 2010… sweet :) .

http://blogs.msdn.com/bharry/archive/2009/10/01/tfs-2010-for-sourcesafe-users.aspx

Running SQL on Entity Framework

by fkollmann 9/5/2009 12:25:37 AM

Easy and clean:

public static DbConnection GetStoreConnection(this ObjectContext oc)
{
    if (oc == null)
        throw new NullReferenceException("oc is null");

    var conn = (EntityConnection)oc.Connection;

    if (conn.State == ConnectionState.Closed)
        conn.Open();

    return conn.StoreConnection;
}

Visual Studio 2008 refuses to bind to TFS or to open solution source controlled

by fkollmann 8/25/2009 7:47:40 PM

We came up with the issue that there are one of the following errors regarding the TFS 2008.

Either you are unable to bind a solution at all, showing:

The solution you have opened is under source control but not currently configured for integrated source control in Visual Studio. …

Or the solution is opened without source control, showing:

The solutions appears to be under source control but its binding information cannot be found. …

Output Window: The solution is offline because its associated Team Foundation Server is offline.

The solution is quite simple: Recreate the server entry in Visual Studio 2008:

1) Close the solution

2) Disconnect the TFS

clip_image002

3) Remove the server

clip_image002[4]

clip_image002[6]

clip_image002[8]

4) Re-add the server

clip_image002[10]

5) Open the solution. Everything should be fine now.

Q: http://markitup.com/Posts/Post.aspx?postId=6355ea6f-3af6-4cfc-86b0-b6467de2cd0d
Q: http://social.msdn.microsoft.com/Forums/en-US/tfsversioncontrol/thread/308255ac-2e10-426c-996c-ca62321c8e1f