July 20, 2018 08:51 by
Peter
In this article, I will be explaining 3 different ways to handle exceptions and display a friendly error page to the end user. Friendly Error Pages are the pages that you design to show the end user when any kind of not handled exception happens in your application and your expected result is not achieved. So, instead of presenting your end user with technical information regarding the exception, you show him a friend page. Also, presenting your end user with technical information is not a security best practice.
So, let's see the three ways.
Method 1: Custom Exception Filter
Custom Exception Filter
It is a filter that is called every time an exception occurs in the applied methods.
Why would I use a custom exception filter?
Because with a custom exception filter, you can handle in a generic way every kind of exception thrown by your actions and/or controllers. You may use custom exception filters to log your exceptions.
Steps to achieve this:
Step 1
Create a new class named CustomExceptionFilter.
public class CustomExceptionFilter : FilterAttribute, IExceptionFilter
{
public void OnException( ExceptionContext filterContext )
{
filterContext.Result = new RedirectResult( "Home/About" );
filterContext.ExceptionHandled = true;
}
}
What this custom exception does is to redirect to your About action in your Home Controller. Do not forget to set the ExceptionHandled equal to true; otherwise it will not take effect.
Step 2
Apply your custom exception filter to your controller/action.
public class HomeController : Controller
{
[CustomExceptionFilter]
public ActionResult Index()
{
throw new Exception();
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application thrown an exception";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
throw new Exception();
return View();
}
}
You can see that the exception filter is applied only to your Index Action so if you access your Contact action, you will be able to see the non-handled exception page.
Method 2: Web.Config configuration
Why would I handle an exception by web.config configuration?
It is easy to configure and useful when you do not need to log or work on the exception.
Steps to achieve this:
Step 1
Include this in your web.config inside the system.web tag.
<customErrors defaultRedirect="Error.cshtml" mode="On"></customErrors>
Step 2
Update your Controller.
public class HomeController : Controller
{
[HandleError]
public ActionResult Index()
{
throw new Exception();
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
throw new Exception();
return View();
}
}
Observation - Like the custom exception filter, you may choose if you want to handle the exceptions at the Controller or Action level. Also, here, the handled exception is applied only to your Index action, you may see the non-handled error in the Contact View.
Method 3: Global.Asax Application_error
What is the Application_error?
It is to override the global exception handler of the application.
Why would I handle an exception by global.asax Application_error?
You do not need to set the places that you would like to handle the errors like before where you had to set the actions and controllers to be handled. Here, every exception will hit and be handled.
Steps to Achieve this:
Step 1
Update your global.asax.
protected void Application_Error( object sender, EventArgs e )
{
Exception exception = Server.GetLastError();
Server.ClearError();
Response.Redirect( "/Home/About" );
}
Like the custom exception handlers, it is very important to ClearError() in the Server. What is done here is the redirection of non-handled exceptions to the About action in the Home Controller. Congratulation, you just learned three good ways of handling exceptions in your application and presenting friendly error pages to your end users.
July 13, 2018 11:21 by
Peter
In this article, we will learn how to list all users with Associated Roles in ASP.NET MVC 5 using Identity. ASP.NET MVC 5 does not come with an inbuilt feature to list users with associated roles by default. However ASP.NET MVC have inbuilt UserManager, SignManager and RoleManager to assist this.
We need this feature in each of our applications as users are to be maintained along with their associated roles. We can apply a number of ideas to do this. In this article, we will learn a very simple way to list users with their associated RoleName as in the figure below.
Step 1
Create a View Model as Users-in-Role_ViewModel
public class Users_in_Role_ViewModel
{
public string UserId { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public string Role { get; set; }
}
Step 2
Add a new method called UsersWithRoles inside ManageUsersController and add the following codes.
public ActionResult UsersWithRoles()
{
var usersWithRoles = (from user in context.Users
select new
{
UserId = user.Id,
Username = user.UserName,
Email = user.Email,
RoleNames = (from userRole in user.Roles
join role in context.Roles on userRole.RoleId
equals role.Id
select role.Name).ToList()
}).ToList().Select(p => new Users_in_Role_ViewModel()
{
UserId = p.UserId,
Username = p.Username,
Email = p.Email,
Role = string.Join(",", p.RoleNames)
});
return View(usersWithRoles);
}
Note - context.Users represents the table AspNetUsers which has navigation property roles which represent the AspNetUserInRoles table.
Step 3
Now, let’s add a View of UsersWithRoles method of ManageUsersController.
@model IEnumerable<MVC5Demo.UI.ViewModels.Users_in_Role_ViewModel>
@{
ViewBag.Title = "Users With Roles";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="box-title">
<b>Users with Roles</b>
</h3>
</div>
<!-- /.box-header -->
<div class="panel-body">
<table class="table table-hover table-bordered table-condensed" id="UsersWithRoles">
<thead>
<tr>
<td><b>Username</b></td>
<td><b>Email</b></td>
<td><b>Roles</b></td>
</tr>
</thead>
@foreach (var user in Model)
{
<tr>
<td>@user.Username</td>
<td>@user.Email</td>
<td>@user.Role</td>
</tr>
}
</table>
</div>
<div class="panel-footer">
<p class="box-title"><b>Total Users till @String.Format("{0 : dddd, MMMM d, yyyy}", DateTime.Now) : </b><span class="label label-primary">@Model.Count()</span></p>
</div>
</div>
@section scripts{
<script>
$(function () {
$('#UsersWithRoles').DataTable({
"paging": true,
"lengthChange": true,
"searching": true,
"ordering": true,
"info": true,
"autoWidth": true
});
});
</script>
}
Now, the above method and View will return the users to their roles.
n