title: C# - Identity Framework and integer UserId - await SignInAsync issue
body: <p>I am working on an MVC5 demo app and attempting to make us of the Identity Framework, in conjunction with Dapper within this. </p>
  
  <p>I have implemented a n-tier hybrid architecture with many layers including the DAL handled by Dapper (with repository pattern). I am using the standard <code>Microsoft.AspNet.Identity</code> with both Owin and Core assemblies correctly referenced for authentication - I read on SO that rolling your own is not advisable!</p>
  
  <p>I digress, the problem I am having is with the following method within my Identity implementation...</p>
  
  <pre><code>PasswordSignInAsync()
  </code></pre>
  
  <p>For example, within my <code>AccountContoller.cs</code> I have the following:</p>
  
  <pre><code> // POST: /Account/Login
      [HttpPost]
      [AllowAnonymous]
      [ValidateAntiForgeryToken]
      public async Task&lt;ActionResult&gt; Login(LoginViewModel model, string returnUrl)
      {
  
          // This doesn't count login failures towards account lockout
          // To enable password failures to trigger account lockout, change to shouldLockout: true
          var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
  
          int userId = Int32.Parse(User.Identity.GetUserId());
  
          switch (result)
          {
              case SignInStatus.Success:
                  ViewBag.UserId = userId;
                  return RedirectToAction("Index",  new RouteValueDictionary(new { controller = "User", action = "Index", id = userId }));
                  //return RedirectToLocal(returnUrl);
              case SignInStatus.LockedOut:
                  return View("Lockout");
              case SignInStatus.RequiresVerification:
                  return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
              case SignInStatus.Failure:
                  return View(model);
              default:
                  ModelState.AddModelError("", "Invalid login attempt.");
                  return View(model);
          }
      }
  </code></pre>
  
  <p>Basically, the method logs users in and if <code>SignInStatus.Success</code> then redirects to my <code>UserController.cs</code> Index method. The Index method accepts an integer id - aka the UserId variable of the authenticated user. </p>
  
  <p>My <code>Index(int id)</code> routes to /Users/{id} or for example /Users/5</p>
  
  <p>However, what happens after submitting the form is:</p>
  
  <blockquote>
    <p>Server Error in '/' Application.</p>
    
    <p>Value cannot be null. Parameter name: String    Description: An
    unhandled exception occurred during the execution of the current web
    request. Please review the stack trace for more information about the
    error and where it originated in the code. </p>
    
    <p>Exception Details: System.ArgumentNullException: Value cannot be
    null. Parameter name: String</p>
    
    <p>Source Error: </p>
    
    <p>Line 77:             var result = await
    SignInManager.PasswordSignInAsync(model.UserName, model.Password,
    model.RememberMe, shouldLockout: false); Line 78:  Line 79:<br>
    int userId = Int32.Parse(User.Identity.GetUserId()); Line 80:<br>
    Line 81:             switch (result)</p>
    
    <p>Source File: 
    c:[ProjectName is omitted]\Controllers\AccountController.cs
    Line:  79 </p>
    
    <p>Stack Trace: </p>
    
    <p>[ArgumentNullException: Value cannot be null. Parameter name: String] 
    System.Number.StringToNumber(String str, NumberStyles options,
    NumberBuffer&amp; number, NumberFormatInfo info, Boolean parseDecimal)
    +12099581<br>
    System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info) 
    +120<br>
    System.Int32.Parse(String s) +24 [ProjectName is omitted for security].Controllers.
    d__4.MoveNext() in
    [ProjectName is omitted]\Controllers\AccountController.cs:79
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
    task) +99<br>
    System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
    task) +58    System.Runtime.CompilerServices.TaskAwaiter.GetResult()
    +26    System.Threading.Tasks.TaskHelpersExtensions.ThrowIfFaulted(Task task)
    +61    System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult
    asyncResult) +114<br>
    System.Web.Mvc.Async.&lt;>c__DisplayClass37.b__36(IAsyncResult
    asyncResult) +66<br>
    System.Web.Mvc.Async.WrappedAsyncResult<code>1.CallEndDelegate(IAsyncResult
    asyncResult) +47<br>
    System.Web.Mvc.Async.WrappedAsyncResultBase</code>1.End() +136<br>
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
    Object tag) +102<br>
    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult
    asyncResult) +49<br>
    System.Web.Mvc.Async.AsyncInvocationWithFilters.b__3d()
    +117    System.Web.Mvc.Async.&lt;>c__DisplayClass46.b__3f()
    +323    System.Web.Mvc.Async.&lt;>c__DisplayClass33.b__32(IAsyncResult asyncResult) +44<br>
    System.Web.Mvc.Async.WrappedAsyncResult<code>1.CallEndDelegate(IAsyncResult
    asyncResult) +47<br>
    System.Web.Mvc.Async.WrappedAsyncResultBase</code>1.End() +136<br>
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
    Object tag) +102<br>
    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult
    asyncResult) +50<br>
    System.Web.Mvc.Async.&lt;>c__DisplayClass2b.b__1c()
    +72    System.Web.Mvc.Async.&lt;>c__DisplayClass21.b__1e(IAsyncResult
    asyncResult) +185<br>
    System.Web.Mvc.Async.WrappedAsyncResult<code>1.CallEndDelegate(IAsyncResult
    asyncResult) +42<br>
    System.Web.Mvc.Async.WrappedAsyncResultBase</code>1.End() +133<br>
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
    Object tag) +56<br>
    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult
    asyncResult) +40<br>
    System.Web.Mvc.Controller.b__1d(IAsyncResult
    asyncResult, ExecuteCoreState innerState) +34<br>
    System.Web.Mvc.Async.WrappedAsyncVoid<code>1.CallEndDelegate(IAsyncResult
    asyncResult) +70<br>
    System.Web.Mvc.Async.WrappedAsyncResultBase</code>1.End() +133<br>
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
    Object tag) +56<br>
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
    Object tag) +37<br>
    System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +44
    System.Web.Mvc.Controller.b__15(IAsyncResult
    asyncResult, Controller controller) +39<br>
    System.Web.Mvc.Async.WrappedAsyncVoid<code>1.CallEndDelegate(IAsyncResult
    asyncResult) +62<br>
    System.Web.Mvc.Async.WrappedAsyncResultBase</code>1.End() +133<br>
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
    Object tag) +56<br>
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
    Object tag) +37    System.Web.Mvc.Controller.EndExecute(IAsyncResult
    asyncResult) +39<br>
    System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult
    asyncResult) +39<br>
    System.Web.Mvc.MvcHandler.b__5(IAsyncResult
    asyncResult, ProcessRequestState innerState) +39<br>
    System.Web.Mvc.Async.WrappedAsyncVoid<code>1.CallEndDelegate(IAsyncResult
    asyncResult) +70<br>
    System.Web.Mvc.Async.WrappedAsyncResultBase</code>1.End() +133<br>
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
    Object tag) +56<br>
    System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult,
    Object tag) +37<br>
    System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
    +40    System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult
    result) +38<br>
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
    +9723757    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp; completedSynchronously) +155</p>
  </blockquote>
  
  <p>I do not want my Index action within the <code>UserController</code> to accept nullable params (i.e. int? id) although making the int nullable would fix it (by loading blank index page) - but the whole point is a Profile belongs to a user and cannot be generic...</p>
  
  <pre><code>    // UserController.cs  /User/Index/5
      // GET: User's Profile page by calling DAL ProfileRepository.cs!
      public ActionResult Index(int id)
      {
          Profile profile = _profileRepository.ProfileGet(id);
          return View(profile);
      }
  </code></pre>
  
  <p>Strange thing is, if I reload the login page and resubmit the login form it manages to assign an integer value to the userId variable and route to their Profile!</p>
  
  <p>I don't know if it is something to do with the await SignInAsync method but surely this should stop the thread executing until the method call is complete?</p>
  
  <p>Or perhaps it's to do with the parsing of the string into an int here:
  <code>int userId = Int32.Parse(User.Identity.GetUserId());</code></p>
  
  <p>but if the <code>SignInAsync</code> has finished successfully there should be a <code>User.Identity</code> to call <code>GetUserId()</code> on right?</p>
  
  <p>So it is strange therefore that Ctrl + F5 after the error dump appearing would then cause the correct Profile page to load - meaning the integer value is correctly assigned.</p>
  
  <p>Bah! I'm at the point where I am considering scrapping the Identity framework - it was tough enough for me decouple it from the horrid EF and use my own DB schema!</p>
  
  <p>If you guys need to see anymore of my source please let me know </p>
  
  <p>All the best,</p>
  
  <p>:-)</p>
  
  <p>or should it be o.O !</p>