I used a specific authorization policy for user log in, so created custom Authorization Handler. And I would like to display use a specific alert message if they failed the
Use TempData to show your message
There are you need ITempDataDictionaryFactory
and IHttpContextAccessor
or for context you can get from mvcContext.HttpContext
if (context.HasFailed && context.Resource is AuthorizationFilterContext mvcContext)
{
var tempData = _tempDataDictionaryFactory.GetTempData(mvcContext.HttpContext);
tempData["message"] = "alert message";
}
then you can get it in Login method via TempData
public IActionResult Login()
{
string message = null;
var item = TempData.FirstOrDefault(x =>x.Key == key);
if (item.Value != null)
{
message = (string)item.Value;
}
return View();
}
Why your code not working:
HttpContext
creating per request it means that you inserting mvcContext.HttpContext.Items["message"] = "alert message";
will be able only for current request, when you use Authorization in controller or his method it will insert you message to current request and redirect to your AccessDeniedPath or LoginPath and new HttpContext
will be created for this request without your message. To share some info between requests you can use TempData or other methods.
Update Try to get httpContext from accessor Here full code
add to startup services.AddSingleton
public class CustomRequirementHandler : AuthorizationHandler
{
private readonly IHttpContextAccessor _httpContext;
private readonly ITempDataDictionaryFactory _tempDataDictionaryFactory;
public CustomRequirementHandler(IHttpContextAccessor httpContext, ITempDataDictionaryFactory tempDataDictionary)
{
_httpContext = httpContext;
_tempDataDictionaryFactory = tempDataDictionary;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement)
{
///////
//Your logic
///////
if (context.HasFailed)
{
var tempData = _tempDataDictionaryFactory.GetTempData(_httpContext.HttpContext);
tempData["message"] = "alert message";
}
return Task.CompletedTask;
}
}
UPDATE When context.Fail(); performed tempData dont injecting via tempdata provider but you can call tempdata provider for executing manual save
Here example:
public class CustomRequirementHandler : AuthorizationHandler
{
private readonly ITempDataProvider _tempDataProvider;
public CustomRequirementHandler(ITempDataProvider tempDataProvider)
{
_tempDataProvider = tempDataProvider;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement)
{
///////
//Your logic
///////
context.Fail();
if (context.HasFailed && context.Resource is AuthorizationFilterContext mvcContext)
{
_tempDataProvider.SaveTempData(mvcContext.HttpContext, new Dictionary() { { "message","alertmessage "+DateTime.Now } });
}
return Task.CompletedTask;
}
}