所以我有一些通用的动作结果,暂时链接到各种视图。布局页面包含对adfs的调用,以填充必须为每个页面登录的用户名。看起来像这样:
<div class="float-right">
<section id="login">
Hello, <span class="username">@ViewBag.GivenName @ViewBag.LastName</span>!
</section>
</div>
在家庭控制器中,这个登录名称的作用是这里的代码:
public ActionResult Index()
{
ClaimsIdentity claimsIdentity = Thread.CurrentPrincipal.Identity as ClaimsIdentity;
Claim claimGivenName = claimsIdentity.FindFirst("http://sts.msft.net/user/FirstName");
Claim claimLastName = claimsIdentity.FindFirst("http://sts.msft.net/user/LastName");
if (claimGivenName == null || claimLastName == null)
{
ViewBag.GivenName = "#FAIL";
}
else
{
ViewBag.GivenName = claimGivenName.Value;
ViewBag.LastName = claimLastName.Value;
}
return View();
}
但如前所述,我需要在用户访问每个链接时显示(actionresult)。因此,我必须将上述所有代码发布到每个actionresult中以实现此目的。
我是否可以通过某种方式将此问题作为一个整体应用于每个操作结果,而不是必须将代码从一个操作复制到另一个操作?我确实尝试注册我的_Layout.cshtml的actionresult并调用那个partialview,但这并没有给我带来有利的结果。我确信这是我想念的简单事。
希望你们中的一些人可以提供帮助。非常感谢。
答案 0 :(得分:1)
我们使用抽象控制器并覆盖其OnActionExecuting
方法,以便在调用实际操作方法之前执行代码。使用这个抽象控制器,您所要做的就是让任何其他控制器继承它以获得它的功能。我们还使用此基本控制器来定义扩展它的其他控制器可以使用的其他辅助方法,例如GetUsernameForAuthenticatedUser()
。
public abstract class AbstractAuthenticationController : Controller
{
private readonly IAuthenticationService _authService;
protected AbstractAuthenticationController()
{
_authService = AuthenticationServiceFactory.Create();
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
EnsureUserIsAuthenticated();
}
internal void EnsureUserIsAuthenticated()
{
if (!_authService.IsUserAuthenticated())
{
_authService.Login();
}
}
protected string GetUsernameForAuthenticatedUser()
{
var identityName = System.Web.HttpContext.Current.User.Identity.Name;
var username = _authService.GetUsername(identityName);
if (username == null) throw new UsernameNotFoundException("No Username for " + identityName);
return username;
}
}
此功能也可以在Attribute
类中实现,它允许您装饰控制器而不是使用继承,但最终结果是相同的。 Here is an example of a custom controller attribute implementation
答案 1 :(得分:0)
您可以创建一个基本控制器并使所有控制器继承它。将设置给定名称和姓氏的代码移动到单独的受保护方法中,并在需要时调用它。我想你可以在基本控制器的Initialize
方法中调用该函数。这样您就不需要直接将其调用到操作中。
您还可以创建模型层次结构,并将GivenName
和LastName
作为基本模型的属性,而不是使用ViewBag
。
答案 2 :(得分:0)
使用OnActionExecuting
的另一种替代方法就是为模板的一部分提供自己的动作方法,返回部分并调用@Html.Action()