I have an A - Z directory 'widget' that I have on every page. If the user is on the home page and they click something in the directory, I want to load up the directory page with the corresponding result loaded. But if the user is on the directory page and they click something, I want to asynchronously load the result without doing a page refresh.
The directory widget has links that point to the DirectoryResult action method on the GroupController, which would normally return a PartialView if they're on the directory page. But if they're not on the directory page, I redirect to the main Directory action method which returns a View and loads the entire page.
This is the code in question:
public ActionResult DirectoryResult(string search)
{
if (Request.IsAjaxRequest())
{
var groups = _groupService.GetGroupsBySearchExpression(search);
var premiumGroups = _groupService.FilterPremiumGroups(groups);
return PartialView(new FundDirectoryViewModel
{
Groups = groups,
PremiumGroups = premiumGroups
});
}
else
{
TempData[UIMessageDataKeys.FundDirectorySearch] = search;
return RedirectToAction("Directory", "Group");
}
}
I showed this to one of the guys in the office and his immediate response was "that's a hack!". I don't know whether to agree with him or not though, because I don't know any better way to do it.
For reference, this is the definition of the widget that exists on every page:
<div id="DirectoryList" class="directory-list">
<span>Fund Directory</span>
<% var letters = new [] { "A", "B", "C", "D", "E", "F", "G", "H", "I", ... }; %>
<% var current = (Model.Search.IsNotNu开发者_Go百科llOrEmpty()) ? Model.Search : "A"; %>
<% foreach (var letter in letters) { %>
<span>
// use HtmlHelper extension to generate links as our system needs them
<%= Html.RouteActionLink("funddirectory", "DirectoryResult"
, letter
, (letter.ToLower() == current) ? new { @class = "active" } : new { @class = "" })%>
</span>
<%} %>
</div>
Is there a better way for me to determine whether I should return a PartialView or a View depending on the page the request comes from?
While your view can definitely be improved to avoid all this spaghetti code (using editor/display templates and HTML helpers and avoid hard-coding an alphabet in a view :-)), the action method seems fine to me. Using Request.IsAjaxRequest
to determine whether the action has been requested with AJAX and return a partial view or if not redirect is perfectly fine.
What could be considered as a hack is the usage of TempData
instead of using a query string because if the user presses F5 on the redirected page he will loose the context, but if this is the behavior you expect then it's ok.
While I am not familiar with the context I would be interested in the arguments that the guys at your office used to support their reaction of this being a hack.
While Darin is 100% correct and your code is not a hack I usually prefer making two Actions with different names and signatures. This is especially easy if you use an AjaxOnly action filter such as: http://helios.ca/2009/05/27/aspnet-mvc-action-filter-ajax-only-attribute/
public ActionResult DirectoryResult(string search)
{
var groups = _groupService.GetGroupsBySearchExpression(search);
var premiumGroups = _groupService.FilterPremiumGroups(groups);
return PartialView(new FundDirectoryViewModel
{
Groups = groups,
PremiumGroups = premiumGroups
});
}
//optional [AjaxOnly]
public ActionResult DirectoryAjaxResult( string search )
{
TempData[UIMessageDataKeys.FundDirectorySearch] = search;
return RedirectToAction("Directory", "Group");
}
精彩评论