I have my controller inheriting a base controller as follows:
using System.Web.Mvc; using DA.Services.IBS.Web.FinancePortalFull.Common;
namespace DA.Services.IBS.Web.FinancePortalFull.Controllers
{
public class DepositController : ControllerPrime
{
public ActionResult Index()
{
return View();
}
}
}
And here is the base controller:
public class ControllerPrime : Controller
{
protected override async void OnAuthentication(AuthenticationContext filterContext)
{
var currentUser = ParseUserNameFromOkta(User.Identity.Name);
if (Session[Constants.SessionVariableCurrentUser] == null)
{
var usersManager = new UsersManager();
var userFinance = await usersManager.FindUser(currentUser);
if (userFinance != null)
{
// var role = await usersManager.GetRoleById(userCarPark.IntranetUserId);
var businessUser = new BusinessUser(userFinance);
HttpContext.User = businessUser;
Session[Constants.SessionVariableCurrentUser] = businessUser;
Session[Constants.SessionVariableCurrentUserId] = businessUser.Detail.UserId;
}
else
{
Response.Redirect("~/Home/AccessDenied");
Response.End();
}
}
else
{
if (Session[Constants.SessionVariableCurrentUser] is BusinessUser)
{
HttpContext.User = Session[Constants.SessionVariableCurrentUser] as BusinessUser;
Session[Constants.SessionVariableCurrentUserId] = ((BusinessUser)HttpContext.User).Detail.UserId;
}
else
{
Response.Redirect("~/Home/AccessDenied");
Response.End();
}
}
}
private string ParseUserNameFromOkta(string receivedUserName)
{
var businessUser = receivedUserName;
var regexPattern = @"^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$";
var matches = Regex.Match(receivedUserName, regexPattern);
if (matches.Success)
{
var domainUser = new MailAddress(receivedUserName);
var staffId = domainUser.User;
var domain = "DCA";
businessUser = $"{domain}\\{staffId}";
}
return businessUser;
}
}
Note: BusinessUser is a simple IPrinciple:
public class BusinessUser : IPrincipal
{
public IIdentity Identity { get; }
public BusinessUser(Business.BDO.BusinessUserDetail userObject)
{
Identity = new GenericIdentity(userObject.EmployeeName);
Detail = userObject;
}
public Business.BDO.BusinessUserDetail Detail { get; set; }
public bool IsInRole(string role) { return true; }
}
Now, while debugging, I notice that before this call is made var userFinance = await usersManager.FindUser(currentUser);
, the partial view for navigation goes ahead and tries to utilize BusinessUser object because of this in cshtml:
@using DA.Services.IBS.Web.FinancePortalFull.Common
@using DA.Services.IBS.Web.FinancePortalFull.Helpers
@{
BusinessUser usr = null;
var user = User as BusinessUser;
if (user != null)
{
usr = user;
}
}
<nav class="navbar-default navbar-static-side" role="navigation">
<div class="sidebar-collapse">
<ul class="nav" id="side-menu">
<li class="nav-header">
<div class="dropdown profile-element">
<span>
<img alt="image" class="img-circle" src="@(Url.Action("UserImage", "UserManagement", new {userName = usr != null ? usr.Detail.StaffId : "-1" }))" />
</span>
<a class="dropdown-toggle" href="#">
<span class="clear">
<span class="block m-t-xs"><strong class="font-bold">@(usr != null ? usr.Detail.EmployeeName : "Not Found")</strong></span>
<span class="text-muted text-xs block">@(usr != null ? usr.Detail.JobTitle : "Unknown")</span>
</span>
</a>
</div>
...
I had to add the null checking logic and the first time run the site, I get no image and my fallback values for name and job title.
Have I got myself into a race-condition like scenario?
I also noticed that once I placed the null checks on the cshtml, I'm capturing an exception at Application_Error
in global.asax as follows:
System.InvalidOperationException
HResult=0x80131509
Message=An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.
Source=mscorlib
StackTrace:
at System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Create()
at DA.Services.IBS.Web.FinancePortalFull.Common.ControllerPrime.OnAuthentication(AuthenticationContext filterContext)
at System.Web.Mvc.Controller.System.Web.Mvc.Filters.IAuthenticationFilter.OnAuthentication(AuthenticationContext filterContext)
at System.Web.Mvc.ControllerActionInvoker.InvokeAuthenticationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.Controller.ExecuteCore()
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
at DA.Services.IBS.Web.FinancePortalFull.MvcApplication.Application_Error() in D:\Projects\DA\TFS\ES\DA Integrated Billing System\Solution\Web\DA.Services.IBS.Web.FinancePortalFull\Global.asax.cs:line 48
User contributions licensed under CC BY-SA 3.0