I am new to ASP.NET (C#) and MVC 5. I'm really enjoying it so far, but want to take a step back and make sure that I'm following best practices here. My controller seems like it may be getting too fat, but perhaps that's just part of it?
This is the Index
action for the TicketsController
in a support ticket application that I'm building to familiarize myself with MVC5. Everything works just fine, but it's starting to smell and I am looking for feedback.
TicketsController -> Index:
/// GET /Tickets/
public ActionResult Index(string sortOrder, int? ShopFilter, bool showAll = false)
{
TicketIndexViewModel ticketIndexVM = new TicketIndexViewModel();
ticketIndexVM.SortOrder = sortOrder;
ticketIndexVM.IdSortParam = String.IsNullOrEmpty(sortOrder) ? "id_asc" : "";
ticketIndexVM.ShopNameSortParam = sortOrder == "shop_desc" ? "shop_asc" : "shop_desc";
ticketIndexVM.StatusSortParam = sortOrder == "status_desc" ? "status_asc" : "status_desc";
ticketIndexVM.ShowAllParam = showAll ? "true" : "";
ticketIndexVM.ShopFilterParam = ShopFilter;
ticketIndexVM.ShopListing = Mapper.Map(db.Shops, new List<ShopViewModel>());
var tickets = from t in db.Tickets.Include(t => t.User).Include(t => t.Shop)
select t;
// hide completed and cancelled tickets
if(!showAll)
{
tickets = tickets.Where(t => t.Status < 3);
}
// shop filtering
if(ShopFilter != null)
{
var shopById = db.Shops.Where(s => s.ShopId == ShopFilter);
if (shopById.Count() > 0)
{
tickets = tickets.Where(t => t.ShopId == ShopFilter);
}
else
{
// that shop doesn't exist.
ticketIndexVM.ShopFilterParam = null;
ticketIndexVM.Errors.Add(
String.Format("No shop exists with the ID# {0}", ShopFilter));
}
}
// handle sorting
switch (sortOrder)
{
case "id_asc":
tickets = tickets.OrderBy(t => t.TicketId);
break;
case "shop_desc":
tickets = tickets.OrderByDescending(t => t.Shop.Name);
break;
case "shop_asc":
tickets = tickets.OrderBy(t => t.Shop.Name);
break;
case "status_desc":
tickets = tickets.OrderByDescending(t => t.Status);
break;
case "status_asc":
tickets = tickets.OrderBy(t => t.Status);
break;
default:
tickets = tickets.OrderByDescending(t => t.TicketId);
break;
}
var ticketsVM = Mapper.Map(tickets, new List<TicketViewModel>());
ticketIndexVM.Tickets = ticketsVM;
return View(ticketIndexVM);
}
Tickets/Index.cshtml
@model Tots.Models.ViewModels.TicketIndexViewModel
@{
ViewBag.Title = "Tickets";
}
@if(Model.ShowAllParam == "true")
{
<h1>All Tickets</h1>
}
else
{
<h1>Open Tickets</h1>
}
<div class="page_toolbar text-right">
@if (Model.ShowAllParam == "true")
{
@Html.ActionLink("Show Open Only", "Index", null, new { @class = "btn btn-success" })
}
else
{
@Html.ActionLink("Show All", "Index", new { showAll = true }, new { @class = "btn btn-success" })
}
@Html.ActionLink("Create New", "Create", null, new { @class = "btn btn-primary" })
</div>
@* Error placeholder: *@
@Html.Partial("_Error", @Model)
<div class="row no-gutters">
<div class="col-md-12">
<p class="result-count">
Displaying <strong>@Model.Tickets.Count</strong> results...
</p>
</div>
</div>
<table class="table">
<thead>
<tr>
<th>
@Html.ActionLink("Ticket ID#", "Index", new { sortOrder = @Model.IdSortParam, showAll = @Model.ShowAllParam, ShopFilter = @Model.ShopFilterParam })
</th>
<th>
Date
</th>
<th>
Submitted By
</th>
<th>
@Html.ActionLink("Shop Name", "Index", new { sortOrder = @Model.ShopNameSortParam, showAll = @Model.ShowAllParam, ShopFilter = @Model.ShopFilterParam })
</th>
<th>
Description
</th>
<th>
@Html.ActionLink("Status", "Index", new { sortOrder = @Model.StatusSortParam, showAll = @Model.ShowAllParam, ShopFilter = @Model.ShopFilterParam })
</th>
<th></th>
</tr>
</thead>
<tbody>
@Html.DisplayFor(x => x.Tickets)
</tbody>
</table>
sortOrder == "shop_desc"
will addshop_asc
as theticketIndexVM.ShopNameSortParam
value when it's true? It seems like those are inverted. \$\endgroup\$*SortParam
values are strictly ViewModel properties (not used in the controllers business logic) and are applied to theActionLink
of the headers in the view to sort by the opposite of what is currently being viewed when clicked. \$\endgroup\$