Thursday, July 20, 2017

C# Func vs Action

The difference between Func and Action is simply whether you want the delegate to return a value (use Func) or not (use Action)

Func is probably most commonly used in LINQ - for example in projections: list.Select(x => x.SomeProperty) or filtering: list.Where(x => x.SomeValue == someOtherValue) or key selection: list.Join(otherList, x => x.FirstKey, y => y.SecondKey, ...)

Action is more commonly used for things like List.ForEach: execute the given action for each item in the list





Traditional way of using Delegate

//Declare delegate
public delegate void PrintMessage(string message);
public delegate int Calculate(int x, int y);


class SimpleClass
{
   public void SayHello(string name)
   {
      Console.WriteLine("Hello {0}", name);
   }


   public int Add(int x, int y)
   {
      return x+y;
   }
}

//Use delegate
var sc = new SimpleClass();
var printer = new PrintMessage(sc.SayHello);
printer("Pollux");

var calculator = new Calculate(sc.Add);
var result = calculator(5,10);



Action

This delegate was introduced in Framework 2.0. We can now use Action delegate to pass a method as a parameter without explicitly defining the delegate. The compiler will take care of it. This delegate can accept parameters but without a return type.

Action act = delegate(string name)
{
   Console.WriteLine("Hello ", name);
};


Call the delegate use act(4, 5)



Func

This was introduced in Framework3.5. This delegate is different from Action in the sense that it supports for return value.

Func fn = delegate(int x, int y)
{
   return x+y;
};


Call the delegate use Console.WriteLine(“Using Func<> :” + fn(6, 6));

Monday, July 3, 2017

How to resolve a System.Security.Principal.IdentityNotMappedException?

Sometimes when working with a non-English version of Windows, we get kinda problem
"Some or all identity references could not be translated"
This indicates that we are getting a System.Security.Principal.IdentityNotMappedException
What does it mean?


The first thing to understand is that in Windows, User Accounts and Groups have a unique and immutable identifier known as a Security Identifier (SID). When working with User Accounts and Groups in Windows, you can work with them via their SID or by their name.

In Windows, a user is represented by an Access Token (You can find more information on Access Tokens at http://msdn.microsoft.com/en-us/library/windows/desktop/aa374909(v=vs.85).aspx) which can be associated with a process or to a thread (via impersonation).
The token contains the user’s SID and all the Groups the user is a member of. The token contains the Group SIDs. (The groups are NOT stored by their names)

There are Win32 APIs that allows an application to translate between the name and the SID:



These Win32 APIs actually calls the LSA APIs. (One difference with these APIs is that they allow to translate multiple names/SIDs instead just one.)


When converting between a Name and a SID and vice versa, you can encounter an error if the translation can’t be done. The common Win32 Error code that you will see is 1332 also known as ERROR_NONE_MAPPED which translates to “No mapping between account names and security IDs was done.”

At the LSA API level where status errors are returned, the error is: STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED. In .NET, the error code is mapped as the following exception:System.Security.Principal.IdentityNotMappedException

Why would the translation APIs fail? Well, the API remarks provides some details on how the translation is done. It uses a lookup order to translate (there is also a local cache as well)

In addition to looking up SIDs for local accounts, local domain accounts, and explicitly trusted domain accounts, LsaLookupSids can look up SIDs for any account in any domain in the Windows forest, including SIDs that appear only in the SIDhistory field of an account in the forest. The SIDhistory field stores the former SIDs of an account that has been moved from another domain. To perform these searches, the function queries the global catalog of the forest.

So a translation failure could happen if you have an issue with your Domain(s) or an issue with SID History. So the first step in determining the issue is identifying which user or SID is the issue. Once you have identified the User or SID, you can then review its relationship with the caller (who is this and what domain do they belong to and what domain does the system belong to where the caller is running)

Finally, a word of advice, internally most APIs are going to be working with SIDs so you can avoid the translation error and improve performance by always trying to work with SIDs.
You’ll notice that most classes in .NET such as IsInRole() allows you to specify a SID instead of the name (via the SecurityIdentifier class). WindowsIdentity.Groups allows you access to the SID as well.


Example:
I want to set permission for a user

static void SetPermission(string directory)
{
   var directoryInfo = new DirectoryInfo(directory);
   var directorySecurity = directoryInfo.GetAccessControl();
   CanonicalizeDacl(directorySecurity);
   directorySecurity.AddAccessRule(new FileSystemAccessRule("BUILTIN\\IIS_IUSRS", FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
   directoryInfo.SetAccessControl(directorySecurity);
}


This code would be failed if it run in a non-English version of Windows because the "BUILTIN\\IIS_IUSRS" could not be translated. Exactly the "BUILTIN" could not be translated. To fix this problem, I could change to remove "BUILTIN" or use an SID instead.

static void SetPermission(string directory)
{
   var directoryInfo = new DirectoryInfo(directory);
   var directorySecurity = directoryInfo.GetAccessControl();
   var sid = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
   directorySecurity.AddAccessRule(new FileSystemAccessRule(sid, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
   directoryInfo.SetAccessControl(directorySecurity);
}


Refer these links for SID
https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
https://msdn.microsoft.com/en-us/library/cc980032.aspx

Using statement inside Vs outside

A namespace declaration looks like: MyCorp.TheProduct.SomeModule.Utilities
This could be equivalence


namespace MyCorp
{
   namespace TheProduct
   {
      namespace SomeModule
      {
         namespace Utilities
         {
            ...
         }
      }
   }
}

The rule to resolve the namespace is: First, search the inner most "scope" for a match. If nothing is found then goes out 1 level, continue searching,next and so on... Until a match is found.
Let check the code

With using outside

using System;
using System.Collections.Generic;
using System.Linq;
//using MyCorp.TheProduct; <-- br="" change="" nothing="" this="" uncommenting="" would=""> using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;

namespace MyCorp.TheProduct.SomeModule.Utilities
{
   class C
   {
      Ambiguous a;
   }
}


In the above case, to find out what type Ambiguous is, the search goes in this order:


  1. Nested types inside C (including inherited nested types)
  2. Types in the current namespace MyCorp.TheProduct.SomeModule.Utilities
  3. Types in namespace MyCorp.TheProduct.SomeModule
  4. Types in MyCorp.TheProduct
  5. Types in MyCorp
  6. Types in the null namespace (the global namespace)
  7. Types in System, System.Collections.Generic, System.Linq, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration, and ThirdParty



With usings inside:
namespace MyCorp.TheProduct.SomeModule.Utilities
{
   using System;
   using System.Collections.Generic;
   using System.Linq;
   using MyCorp.TheProduct;
   using MyCorp.TheProduct.OtherModule;
   using MyCorp.TheProduct.OtherModule.Integration;
   using ThirdParty;

   class C
   {
      Ambiguous a;
   }
}


Now, search for the type Ambiguous goes in this order:

  1. Nested types inside C (including inherited nested types)
  2. Types in the current namespace MyCorp.TheProduct.SomeModule.Utilities
  3. Types in System, System.Collections.Generic, System.Linq, MyCorp.TheProduct, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration, and ThirdParty
  4. Types in namespace MyCorp.TheProduct.SomeModule
  5. Types in MyCorp (MyCorp.TheProduct is already searched)
  6. Types in the null namespace (the global namespace)



No matter what we put the using inside or outside the namespace declaration, there's always the possibility that someone add a new type later with identical name ambiguous to one of the namespaces which has higher priority.
Also, if a nested namespace has the same name as a type, it can cause problems.

It's always dangerous to move the using form outside to inside and vice versa. The search hierarchy is changed and another type would be found. Therefore, chose one convention and stick to it.

One advantage of having using outside is that we can rename the using directives look like using AC=System.Security.AccessControl