Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Sunday, May 6, 2018

FIFO Semaphore

In one of our project requirement we had to built the max concurrency requirement for which we decided to use Semaphore but we had requirement to build FIFO Semaphore as by default Semaphore does not guarantee FIFO access to waiting thread.

Therefore, I have use ConcurrentQueue together with Semaphore to come with FIFO Sempahore




using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Shared.Locking
{
    public class ThreadPoolAsyncLock
    {
        private ConcurrentQueue<(SemaphoreSlim Semaphore, DateTime Time)> queue = new ConcurrentQueue<(SemaphoreSlim, DateTime)>();

        private (DateTime start, int requests) requestTime = (DateTime.UtcNow, 0);

        private SemaphoreSlim semaphoreSlims;

        public static TimeSpan Timeout = TimeSpan.FromMilliseconds(500);

        public static int MaxRequest = 30;

        public ThreadPoolAsyncLock(int maxThread = 30)
        {
            semaphoreSlims = new SemaphoreSlim(maxThread, maxThread);
        }

        public async Task<TaskRunner<TResult>> ScheduleTask<TResult>()
        {
            /* This lock will make sure no one enter in main semaphore unless some one from main semaphore releases this */
            await AcquireOrQueue().WaitAsync(Timeout).ConfigureAwait(false);

            /* Main semaphore wait */
            if (await semaphoreSlims.WaitAsync(Timeout).ConfigureAwait(false))
               {
                 new TaskRunner<TResult>(ReleaseLock) { IsLocked = true };
               }


            return new TaskRunner<TResult>(ReleaseLock);
        }

        private SemaphoreSlim AcquireOrQueue()
        {
            SemaphoreSlim slim = null;
            lock (semaphoreSlims)
            {
                if (semaphoreSlims.CurrentCount > 0 && (DateTime.UtcNow.Subtract(requestTime.start).Seconds > 1 || requestTime.requests < MaxRequest))
                {
                    slim = new SemaphoreSlim(1, 1);
                    Interlocked.Increment(ref requestTime.requests);
                }
                else
                {
                    slim = new SemaphoreSlim(0, 1);
                    queue.Enqueue((slim, DateTime.UtcNow));
                }
            }

            return slim;
        }

        /// <summary>
        /// Dequeue the thread waiting to enter main semaphore
        /// </summary>
        /// <remarks>
        /// It only allows the dequeue if the main semaphore is not full Or Max requests hasn't been reached within last second.
        /// </remarks>
        private void DeQueue()
        {
            lock (semaphoreSlims)
            {
                if (semaphoreSlims.CurrentCount == 0 || (requestTime.requests >= MaxRequest && DateTime.UtcNow.Subtract(requestTime.start).Seconds <= 1))
                    return;

                Interlocked.Decrement(ref requestTime.requests);
                if (queue.TryDequeue(out var semaphore))
                {
                    semaphore.Semaphore.Release();
                    requestTime.start = semaphore.Time;
                }
            }
        }

        private void ReleaseLock()
        {
            lock (semaphoreSlims)
            {
                semaphoreSlims.Release();
                DeQueue();
            }
        }

        /// <summary>
        /// The disposable releaser tasked with releasing the semaphore.
        /// </summary>
        public sealed class TaskRunner<TResult> : IDisposable
        {
            /// <summary>
            /// A value indicating whether this instance of the given entity has been disposed.
            /// </summary>
            /// <value><see langword="true"/> if this instance has been disposed; otherwise, <see langword="false"/>.</value>
            /// <remarks>
            /// If the entity is disposed, it must not be disposed a second
            /// time. The isDisposed field is set the first time the entity
            /// is disposed. If the isDisposed field is true, then the Dispose()
            /// method will not dispose again. This help not to prolong the entity's
            /// life in the Garbage Collector.
            /// </remarks>
            private bool isDisposed;

            
            public bool IsLocked { get; set; }

            /// <summary>
            /// A Task to run after acquiring and locking the thread.
            /// </summary>
            /// <remarks>
            /// If the entity acquires the lock, then entity shoule call <see cref="RunAsycn" /> or <see cref="Run"/> to run the task />
            /// </remarks>
            private Task<TResult> task;

            public delegate void TaskDisposeCallBack();

            /// <summary>
            /// Task dispose call back to release or dispose any resources requried for this runner.
            /// </summary>
            private TaskDisposeCallBack taskDisposeCallBack;

            public TaskRunner(TaskDisposeCallBack callBack)
            {
                taskDisposeCallBack = callBack;
            }

            /// <summary>
            /// Finalizes an instance of the <see cref="TaskRunner{TResult}"/> class.
            /// </summary>
            ~TaskRunner()
            {
                // Do not re-create Dispose clean-up code here.
                // Calling Dispose(false) is optimal in terms of
                // readability and maintainability.
                this.Dispose(false);
            }

            /// <summary>
            /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
            /// </summary>
            public void Dispose()
            {
                this.Dispose(true);

                // This object will be cleaned up by the Dispose method.
                // Therefore, you should call GC.SuppressFinalize to
                // take this object off the finalization queue
                // and prevent finalization code for this object
                // from executing a second time.
                GC.SuppressFinalize(this);
            }

            /// <summary>
            /// Disposes the object and frees resources for the Garbage Collector.
            /// </summary>
            /// <param name="disposing">
            /// If true, the object gets disposed.
            /// </param>
            private void Dispose(bool disposing)
            {
                if (this.isDisposed)
                {
                    return;
                }

                if (disposing)
                {
                    taskDisposeCallBack?.Invoke();
                }

                // Call the appropriate methods to clean up
                // unmanaged resources here.
                // Note disposing is done.
                this.isDisposed = true;
            }
        }
    }
}


Usage


    using (var @lock = await new ThreadPoolAsyncLock().ScheduledTask().ConfigureAwait(false))
            {
                if (@lock.IsLocked)
                    return query.Track().Skip((page - 1) * count).Take(count).GetResult();

                throw new HttpResponseException((HttpStatusCode)429);
            }


Tuesday, April 17, 2018

Web API Default Behaviour Overriding

Overriding Text Encoding

In one of our project we had an issue where one of invalid text character in web api was throwing exception instead of removing or replacing that bad character. After investigating we figure out that the default Encoding was UTF8 but EncoderFallback was set to throw Exception for invalid character instead of replacing with default Character.

Therefore, we just added this one below line to replace the text encoding behaviour

            config.Formatters.JsonFormatter.SupportedEncodings[0] = Encoding.UTF8;

The default system UTF8 Encoding fallback set to replace invalid character with "?"

public static void ConfigureWebApi(HttpConfiguration config)
        {
            ...
            ...

        // HACK: To allow JSON serialization to handle invalid characters
            config.Formatters.JsonFormatter.SupportedEncodings[0] = Encoding.UTF8;
            config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
            config.Services.Replace(typeof(IExceptionLogger), new GlobalExceptionLogger());
        }

Overriding GlobalExceptionHandler

We are using Azure Telemetry to log all of our errors therefore, we wanted to override the global exception handler to log all errors to telemetry. This is similar concept of Global.ascx function for web api.

the below line will replace the GlobalExceptionHandler for WebApi

            config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());


   public class GlobalExceptionHandler : ExceptionHandler
    {
        public override void Handle(ExceptionHandlerContext context)
        {
            var exception = context.Exception;
            var message = context.Exception.GetType().Name + ": " + context.Exception.Message;

            if (exception is HttpException httpException)
            {
                context.Result = new CustomErrorResult(context.Request, (HttpStatusCode)httpException.GetHttpCode(), message);
                return;
            }

            // Return HttpStatusCode for other types of exception.
            context.Result = new CustomErrorResult(context.Request, HttpStatusCode.BadRequest, message);
        }
    }
 


public class CustomErrorResult : IHttpActionResult
    {
        private readonly string _errorMessage;
        private readonly HttpRequestMessage _requestMessage;
        private readonly HttpStatusCode _statusCode;

        public CustomErrorResult(HttpRequestMessage requestMessage, HttpStatusCode statusCode, string errorMessage)
        {
            _requestMessage = requestMessage;
            _statusCode = statusCode;
            _errorMessage = errorMessage;
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            return Task.FromResult(_requestMessage.CreateErrorResponse(_statusCode, _errorMessage));
        }
    }
  


Overriding GlobalExceptionLogger

We also wanted to replace the GlobalExceptionLogger to be our ExceptionLogger to push all errors to Azure Telemetry.

            config.Services.Replace(typeof(IExceptionLogger), new GlobalExceptionLogger());


public class GlobalExceptionLogger : ExceptionLogger
    {
        public override void Log(ExceptionLoggerContext context)
        {
            new TelemetryClient().TrackException(context.Exception);
        }
    }
 

Tuesday, December 19, 2017

Azure Storage Account File Storage Wrapper For Basic Functions

In one of our project we had to upload/download files to azure file storage.
Therefore, I build this small wrapper classes to make use of Azure file storage easy.

AzureStorageAccountClient

This client is supposed to provide function to connect to different storage account such as (Blob, File and etc storage)


    public class AzureStorageAccountClient
    {
        private readonly ILogger logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        public AzureStorageAccountClient(string connectionString)
        {
            ConnectionString = connectionString;
        }

        public string ConnectionString { get; }

        public IAzureStorageShareClient FileClientConnect()
        {
            string message = string.Empty;
            try
            {
                return new AzureStorageShareClient(CloudStorageAccount.Parse(ConnectionString).CreateCloudFileClient());
            }
            catch (Exception ex)
            {
                logger.Critical("Error in Azure Client", ex);
                throw;
            }
        }
    }


AzureStorageShareClient

This class provides functions to perform on share storage client.


   public interface IAzureStorageShareClient
    {
        CloudFileClient CloudFileClient { get; }
    }

    public class AzureStorageShareClient : IAzureStorageShareClient
    {
        public AzureStorageShareClient(CloudFileClient cloudFileClient)
        {
            CloudFileClient = cloudFileClient;
        }

        public CloudFileClient CloudFileClient { get; }
    }   



AzureStorageFileDirectoryClient

This class provides functionality to different Directoy related operations.


    public interface IAzureStorageFileDirectoryClient
    {
        CloudFileShare CloudFileShare { get; }

        CloudFileDirectory CloudFileDirectory { get; set; }
    }

    public class AzureStorageFileDirectoryClient : IAzureStorageFileDirectoryClient
    {
        public AzureStorageFileDirectoryClient(CloudFileShare cloudFileShare)
        {
            CloudFileShare = cloudFileShare;
        }

        public CloudFileShare CloudFileShare { get; }

        public CloudFileDirectory CloudFileDirectory { get; set; }
    }


AzureStorageFileClient

This class provides functions to different File related operations


    public interface IAzureStorageFileClient
    {
        CloudFileDirectory CloudFileDirectory { get; set; }

        CloudFile CloudFile { get; }
    }

    public class AzureStorageFileClient : IAzureStorageFileClient
    {
        public AzureStorageFileClient(CloudFile cloudFile)
        {
            CloudFile = cloudFile;
        }

        public CloudFileDirectory CloudFileDirectory { get; set; }

        public CloudFile CloudFile { get; }
    }



As you have noted none of the above classes have any functions.
Below is the extension class that provides functions available to those interfaces.

AzureStorageAccountExtensions


    public static class AzureStorageAccountExtensions
    {
        public static async Task GetOrAddShare(this IAzureStorageShareClient client, string shareName)
        {
            var cloudFileShare = client.CloudFileClient.GetShareReference(shareName);
            await cloudFileShare.CreateIfNotExistsAsync().ConfigureAwait(false);
            return new AzureStorageFileDirectoryClient(cloudFileShare);
        }

        public static async Task GetOrAddFolder(this IAzureStorageFileDirectoryClient client, string folderPath)
        {
            var cloudRootDirectory = client.CloudFileShare.GetRootDirectoryReference();
            var cloudFileDirectory = cloudRootDirectory.GetDirectoryReference(folderPath);
            await cloudFileDirectory.CreateIfNotExistsAsync().ConfigureAwait(false);
            client.CloudFileDirectory = cloudFileDirectory;
            return client;
        }

        public static IEnumerable ListFiles(this IAzureStorageFileDirectoryClient client)
        {
            return client.CloudFileDirectory.ListFilesAndDirectories().Where(f => !f.Uri.LocalPath.Contains(".folder"));
        }

        public static async Task AddFile(this IAzureStorageFileDirectoryClient client, string fileName, long length)
        {
            await client.CloudFileDirectory.CreateIfNotExistsAsync().ConfigureAwait(false);

            var cloudFile = client.CloudFileDirectory.GetFileReference(fileName);
            if (!await cloudFile.ExistsAsync().ConfigureAwait(false))
            {
                await cloudFile.CreateAsync(length).ConfigureAwait(false);
            }

            return new AzureStorageFileClient(cloudFile);
        }

        public static async Task GetFile(this IAzureStorageFileDirectoryClient client, string fileName)
        {
            var cloudFile = client.CloudFileDirectory.GetFileReference(fileName);
            if (await cloudFile.ExistsAsync().ConfigureAwait(false))
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    await cloudFile.DownloadToStreamAsync(ms).ConfigureAwait(false);
                    return ms.ToArray();
                }
            }

            return null;
        }

        public static async void UploadFile(this IAzureStorageFileClient client, byte[] data)
        {
            await client.CloudFile.UploadFromByteArrayAsync(data, 0, data.Length).ConfigureAwait(false);
        }
    }



Wednesday, December 7, 2016

Using ExpandoObject with Dictionary to get rid of magic string

In most of the project we used the dictionary and along with dictionary there comes magic string.

In order to get rid of the magic string from code I utilize the ExpandoObject to add/update dictionary item by converting ExpandoObject into dynamic instance.

Usage

 
     Dictionary<string, string> dictoinary = new Dictionary<string, string>();
     dictoinary["FName"] = "Murtaza";
     dictoinary["LName"] = "Ali";
     dictoinary["DOB"] = "1/1/1001";

     var dynamicDictioinary = new DictionaryExpando<string>(dictoinary) as dynamic ;
     dynamicDictioinary.Gender = "Definitely Not Female";
     Console.WriteLine(dynamicDictioinary.FName);
     dynamicDictioinary.FName = "Murtaza Override";
     Console.WriteLine(dynamicDictioinary.FName);
     Console.WriteLine(dynamicDictioinary.Gender);

DictionaryExpando Class

 
    [Serializable]
    class DictionaryExpando<TValue> : DynamicObject
    {
        /// <summary>
        /// Instance of object passed in
        /// </summary>
        public Dictionary<string, TValue> Instance;

        /// <summary>
        /// Cached type of the instance
        /// </summary>
        private Type InstanceType;

        private PropertyInfo[] InstancePropertyInfo
        {
            get
            {
                if (_InstancePropertyInfo == null && Instance != null)
                    _InstancePropertyInfo =
                        Instance.GetType()
                                .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
                return _InstancePropertyInfo;
            }
        }

        private PropertyInfo[] _InstancePropertyInfo;


        public Dictionary<string,TValue> Properties = new Dictionary<string, TValue>();


        /// <summary>
        /// Allows passing in an existing instance variable to 'extend'.        
        /// </summary>
        /// <remarks>
        /// You can pass in null here if you don't want to 
        /// check native properties and only check the Dictionary!
        /// </remarks>
        /// <param name="instance"></param>
        public DictionaryExpando(Dictionary<string, TValue> instance)
        {
            Initialize(instance);
        }


        protected virtual void Initialize(Dictionary<string, TValue> instance)
        {
            Instance = instance;
            if (instance != null)
                InstanceType = instance.GetType();
        }


        /// <summary>
        /// Try to retrieve a member by name first from instance properties
        /// followed by the collection entries.
        /// </summary>
        /// <param name="binder"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = default(TValue);

            // first check the Properties collection for member
            if (Properties.Keys.Contains(binder.Name))
            {
                result = Properties[binder.Name];
                return true;
            }


            // Next check for Public properties via Reflection
            if (Instance != null)
            {
                try
                {
                    return GetProperty(Instance, binder.Name, out result);
                }
                catch
                {
                }
            }

            // failed to retrieve a property
            result = null;
            return false;
        }


        /// <summary>
        /// Property setter implementation tries to retrieve value from instance 
        /// first then into this object
        /// </summary>
        /// <param name="binder"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {

            // first check to see if there's a native property to set
            if (Instance != null)
            {
                try
                {
                    bool result = SetProperty(Instance, binder.Name, value);
                    if (result)
                        return true;
                }
                catch
                {
                }
            }

            // no match - set or add to dictionary
            Properties[binder.Name] = (TValue)value;
            return true;
        }

        /// <summary>
        /// Dynamic invocation method. Currently allows only for Reflection based
        /// operation (no ability to add methods dynamically).
        /// </summary>
        /// <param name="binder"></param>
        /// <param name="args"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            if (Instance != null)
            {
                try
                {
                    // check instance passed in for methods to invoke
                    if (InvokeMethod(Instance, binder.Name, args, out result))
                        return true;
                }
                catch
                {
                }
            }

            result = null;
            return false;
        }


        /// <summary>
        /// Reflection Helper method to retrieve a property
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="name"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        protected bool GetProperty(object instance, string name, out object result)
        {
            if (instance == null)
                instance = this;
            result = default(TValue);
            try
            {
                var dictonary = instance as Dictionary<string, TValue>;
                result = dictonary[name];
                return true;

            }
            catch (Exception)
            {
            }

            return false;
        }

        /// <summary>
        /// Reflection helper method to set a property value
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        protected bool SetProperty(object instance, string name, object value)
        {
            if (instance == null)
                instance = this;

            try
            {
                Dictionary<string, TValue> dictionary = instance as Dictionary<string, TValue>;
                dictionary[name] = (TValue)value;
                return true;
            }
            catch (Exception)
            {
            }

            return false;
        }

        /// <summary>
        /// Reflection helper method to invoke a method
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="name"></param>
        /// <param name="args"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        protected bool InvokeMethod(object instance, string name, object[] args, out object result)
        {
            if (instance == null)
                instance = this;

            // Look at the instanceType
            var miArray = InstanceType.GetMember(name,
                                                 BindingFlags.InvokeMethod |
                                                 BindingFlags.Public | BindingFlags.Instance);

            if (miArray != null && miArray.Length > 0)
            {
                var mi = miArray[0] as MethodInfo;
                result = mi.Invoke(Instance, args);
                return true;
            }

            result = null;
            return false;
        }



        /// <summary>
        /// Convenience method that provides a string Indexer 
        /// to the Properties collection AND the strongly typed
        /// properties of the object by name.
        /// 
        /// // dynamic
        /// exp["Address"] = "112 nowhere lane"; 
        /// // strong
        /// var name = exp["StronglyTypedProperty"] as string; 
        /// </summary>
        /// <remarks>
        /// The getter checks the Properties dictionary first
        /// then looks in PropertyInfo for properties.
        /// The setter checks the instance properties before
        /// checking the Properties dictionary.
        /// </remarks>
        /// <param name="key"></param>
        /// 
        /// <returns></returns>
        public object this[string key]
        {
            get
            {
                try
                {
                    // try to get from properties collection first
                    return Properties[key];
                }
                catch (KeyNotFoundException ex)
                {
                    // try reflection on instanceType
                    object result = null;
                    if (GetProperty(Instance, key, out result))
                        return result;

                    // nope doesn't exist
                    throw;
                }
            }
            set
            {
                if (Properties.ContainsKey(key))
                {
                    Properties[key] = (TValue)value;
                    return;
                }

                // check instance for existance of type first
                var miArray = InstanceType.GetMember(key, BindingFlags.Public | BindingFlags.GetProperty);
                if (miArray != null && miArray.Length > 0)
                    SetProperty(Instance, key, value);
                else
                    Properties[key] = (TValue)value;
            }
        }


        /// <summary>
        /// Returns and the properties of 
        /// </summary>
        /// <param name="includeProperties"></param>
        /// <returns></returns>
        public IEnumerable<KeyValuePair<string, object>> GetProperties(bool includeInstanceProperties = false)
        {
            if (includeInstanceProperties && Instance != null)
            {
                foreach (var prop in this.InstancePropertyInfo)
                    yield return new KeyValuePair<string, object>(prop.Name, prop.GetValue(Instance, null));
            }

            foreach (var key in this.Properties.Keys)
                yield return new KeyValuePair<string, object>(key, this.Properties[key]);

        }


        /// <summary>
        /// Checks whether a property exists in the Property collection
        /// or as a property on the instance
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Contains(KeyValuePair<string, object> item, bool includeInstanceProperties = false)
        {
            bool res = Properties.ContainsKey(item.Key);
            if (res)
                return true;

            if (includeInstanceProperties && Instance != null)
            {
                foreach (var prop in this.InstancePropertyInfo)
                {
                    if (prop.Name == item.Key)
                        return true;
                }
            }

            return false;
        }

    }



Instance

The Isntance property will return the real dictionary object to perform additional operations if required. You may need convert dynamic object back into ExpandoObject

 public Dictionary<string, TValue> Instance;
  

TryGetMember and GetProperty

TryGetMember is overridden method of ExpandoObject in order to fetch the value of provided propertyname. The dynamic property name can be retrieved from binder.Name.

GetProperty fetches the value from dictionary for provided key.

 
     public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = default(TValue);

            // first check the Properties collection for member
            if (Properties.Keys.Contains(binder.Name))
            {
                result = Properties[binder.Name];
                return true;
            }


            // Next check for Public properties via Reflection
            if (Instance != null)
            {
                try
                {
                    return GetProperty(Instance, binder.Name, out result);
                }
                catch
                {
                }
            }

            // failed to retrieve a property
            result = null;
            return false;
        }

  protected bool GetProperty(object instance, string name, out object result)
        {
            if (instance == null)
                instance = this;
            result = default(TValue);
            try
            {
                var dictonary = instance as Dictionary<string, TValue>;
                result = dictonary[name];
                return true;

            }
            catch (Exception)
            {
            }

            return false;
        }


TrySetMember and SetProperty

TrySetMember is overridden method of ExpandoObject in order to set the value of provided propertyname. The dynamic property name can be retrieved from binder.Name.

SetProperty sets the value to dictionary for provided key

 
 public override bool TrySetMember(SetMemberBinder binder, object value)
        {

            // first check to see if there's a native property to set
            if (Instance != null)
            {
                try
                {
                    bool result = SetProperty(Instance, binder.Name, value);
                    if (result)
                        return true;
                }
                catch
                {
                }
            }

            // no match - set or add to dictionary
            Properties[binder.Name] = (TValue)value;
            return true;
        }

      protected bool SetProperty(object instance, string name, object value)
        {
            if (instance == null)
                instance = this;

            try
            {
                Dictionary<string, TValue> dictionary = instance as Dictionary<string, TValue>;
                dictionary[name] = (TValue)value;
                return true;
            }
            catch (Exception)
            {
            }

            return false;
        }


Note: If you wan to use the remove function of dictionary then you may still need to use the magic string to remove the key from dictionary.

Wednesday, July 23, 2014

Resetting password without knowing old password and also by providing secret answer together in one application

In some application we might want to let user change their passwords through secret answer or by entering their old password or without getting their old password.
What if user forgets these information and we want an admin to generate new temporary password for user so they can login and change their password again.
These all things cannot be achieved by just providing one membership provider. Therefore, we would need to add two membership provider and will switch to appropriate provider when required.

Lets consider below two config settings for membership provider


 <membership defaultProvider="SqlServerMembershipProvider" userIsOnlineTimeWindow="10" hashAlgorithmType="HMACSHA512">  
    <providers>  
     <clear />  
     <add name="SqlServerMembershipProvider" requiresQuestionAndAnswer="false" passwordFormat="Hashed" />  
     <add name="SqlServerMembershipProviderRequiresSecretAnswer" requiresQuestionAndAnswer="true" passwordFormat="Hashed" />  
    </providers>  
   </membership>  

I have removed the unrelated attributes from the providers for the brevity. The change in above two providers is requiredQuestionAndAnswer="true" in one provider and in other it is set to false.

Normally for a user to change password the process is they click on forgot password link
Then we ask for username or email and then we sent email to user with reset password link and on that specific link we ask user to provide new password. This process is fine as we are updating password without knowing new password.
Most of the developer would write below code to update password
 
  public bool UpdateMemberPassword(string username, string newPassword)  
     {  
       if (string.IsNullOrWhiteSpace(username))  
         throw new ArgumentNullException("username");  
       if (string.IsNullOrWhiteSpace(newPassword))  
         throw new ArgumentNullException("newPassword");  
       MembershipUser user = GetMemberByUsername(username);  
       if (user == null)  
         throw new Exception("user could not be found");  
       // Membership change password without knowing the old password http://stackoverflow.com/questions/5013901/asp-net-membership-change-password-without-knowing-old-one  
       bool isChanged = user.ChangePassword(user.ResetPassword(), newPassword);  
       return isChanged;  
     }  

Now if you also want to allow the user to change password through secret question and answer then the default provider would not work as it has set requireQuestionAnswer="false".




membershipProvider.ResetPassword(userName, answer); 

 
 
 The provided function will always update the user password regardless the provided answer is correct or not as the required secret queston answer is set to false.

So how do we work around. Here the second provider comes into play which has set requrieQuestionAnswer="true"

If user wants to change password through secret question and answer you will have to change the function as below

 
 public bool ValidateAnswerForUser(string userName, string answer)  
     {  
       if (string.IsNullOrWhiteSpace(userName))  
         throw new ArgumentNullException("userName");  
       if (string.IsNullOrWhiteSpace(answer))  
         throw new ArgumentNullException("answer");  
       MembershipUser user = GetMemberByUsername(userName);  
       if (user == null)  
         throw new ArgumentNullException("user does not exists");  
       string password;  
       try  
       {  
         /* The reason for using different membership provider other than default one is that,  
         * the default has set requiresQuestionAndAnswer="false" so, even if you provide the wrong secret answer provider will simply reset the password.  
         * Therefore, here i am switching the provider with configuration requiresQuestionAndAnswer="true" so if user provides the wrong answer then it will throw exception"  
         */  
         var membershipProvider = Membership.Providers["SqlServerMembershipProviderRequiresSecretAnswer"];  
         if (membershipProvider != null)  
         {  
           password = membershipProvider.ResetPassword(userName, answer);  
         }  
         else  
         {  
           password = Membership.Provider.ResetPassword(userName, answer);  
         }  
       }  
       catch (MembershipPasswordException e)  
       {  
         return false;  
       }  
       if (string.IsNullOrWhiteSpace(password))  
         return false;  
       return true;  
     }  

This will update the password only if provided answer matches the answer in system.

Thursday, July 7, 2011

Request.QueryString Extension Method

Below are two extension methods that I have created for Request.QueryString.. as I am passing many parameters and playing with querystring a lot and every where i had to put IF condition for null and other things..

In order save myself from checking and validating again and again i have designed these two extension Method using some help from internet to save time and reduce number of lines of code.. kindly check them and you are welcome to criticize in constructive way.

I have some more functions in my mind to overload for Request.QueryString and will add later As following two functions have fulfilled my need

How to use..
byte? valueByte  
Guid? valueGuid

//check if "Server" key exits if yes then return value else return default value of null that we have passed

valueByte = Request.QueryString.GetValue<byte?>(Constants.FilterServer, null);
valueGuid = Request.QueryString.GetValue<Guid?>(Constants.FilterGuid, null);

//checks if "Server" Key exists then out value to provided variable and return true to if condition, else return false and assign default value to provided out variable
if(Request.TryParse<byte?>(Constants.FilterServer, null, out valueByte)){}

if(Request.TryParse<Guid?>(Constants.FilterGuid, null, out valueGuid)){}



public static T GetValue<T>(this NameValueCollection collection, string key, T defaultValue)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
var value = collection[key];
if (value == null) { return defaultValue; }
var converter = TypeDescriptor.GetConverter(typeof(T));
if (!converter.CanConvertFrom(typeof(string))) {
throw new ArgumentException(String.Format("Cannot convert ' {0} ' to {1} ", value, typeof(string))); }
return (T)converter.ConvertFrom(value); }


public static bool TryParse<T>(this NameValueCollection collection, string key, T defaultValue, out T returnValue)
{
returnValue = default(T);
try
{ if (collection == null) {
throw new ArgumentNullException("collection"); }
var value = collection[key];
if (value == null)
{ return false;}
var converter = TypeDescriptor.GetConverter(typeof(T)); if (!converter.CanConvertFrom(typeof(string)))
{ throw new ArgumentException(String.Format("Cannot convert ' {0}' to {1} ", value, typeof(string))); }
returnValue = (T)converter.ConvertFrom(value);
return true; }
catch (ArgumentNullException ex) { return false;}
catch (ArgumentException ex) { return false;}
catch (NotSupportedException ex) {return false;} }