How to decouple relational MVC data - asp.net-mvc

Consider this Scenario:
I want to build an MVC application for Northwind Database. I want to have a view that list some orders and I want to create links for CustomerID and EmployeeID and a details link for [OrderDetails] so that when a user clicks any of these links related data will appear in the same page.
My problem is how to decouple this data that is interrelated into views and controllers that show related data in a page, and controllers responsible for individual parts of the information.
Also, how do I configure routing for this sample?
<table width="500px">
<tr>
<th></th>
<th>
OrderID
</th>
<th>
CustomerID
</th>
<th>
EmployeeID
</th>
<th>
OrderDate
</th>
<th>
RequiredDate
</th>
<th>
ShippedDate
</th>
<th>
ShipVia
</th>
<th>
OrderDetails
</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%: Html.ActionLink("Edit", "Edit", new { id=item.OrderID }) %> |
<%: Html.ActionLink("Details", "Details", new { id=item.OrderID })%> |
<%: Html.ActionLink("Delete", "Delete", new { id=item.OrderID })%>
</td>
<td>
<%: item.OrderID %>
</td>
<td>
<%: item.CustomerID %>
</td>
<td>
<%: item.EmployeeID %>
</td>
<td>
<%: String.Format("{0:g}", item.OrderDate) %>
</td>
<td>
<%: String.Format("{0:g}", item.RequiredDate) %>
</td>
<td>
<%: String.Format("{0:g}", item.ShippedDate) %>
</td>
<td>
<%: item.ShipVia %>
</td>
<td>
<%: Html.ActionLink("OrderDetails", "GetOrderDetails", new { id = item.OrderID })%>
</td>
</tr>
<% } %>
</table>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
<div>
<p>
<% Html.RenderPartial("GetOrderDetails"); %>
</p>
<%--<uc1:GetOrderDetails ID="GetOrderDetails1" runat="server" />--%>
</div>
and Order Details partial view:
<table>
<tr>
<th></th>
<th>
OrderID
</th>
<th>
ProductID
</th>
<th>
UnitPrice
</th>
<th>
Quantity
</th>
<th>
Discount
</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%: Html.ActionLink("Edit", "Edit", new { id=item.OrderID }) %> |
<%: Html.ActionLink("Details", "Details", new { id=item.OrderID })%> |
<%: Html.ActionLink("Delete", "Delete", new { id=item.OrderID })%>
</td>
<td>
<%: item.OrderID %>
</td>
<td>
<%: item.ProductID %>
</td>
<td>
<%: String.Format("{0:F}", item.UnitPrice) %>
</td>
<td>
<%: item.Quantity %>
</td>
<td>
<%: item.Discount %>
</td>
</tr>
<% } %>
</table>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
global.asax:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default2", // Route name
"{controller}/{action}/{OrderId}/{CustomerID}", // URL with parameters
new { controller = "NorthwindOrders", action = "Index", OrderId = UrlParameter.Optional, CustomerID = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
Given this structure; how I can display order details under the order list when any of the OrderDetails links are clicked?
And, why is the URL displayed like this when I click on OrderDetails links:
http://localhost:49444/NorthwindOrders/GetOrderDetails?id=10250
I want the URL to display this way:
http://localhost:49444/NorthwindOrders/GetOrderDetails/10250

For your routing question:
if you set up a route like so:
routes.MapRoute(
"orderdetails", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "NorthwindOrders", action = "GetOrderDetails", id = UrlParameter.Optional, CustomerID = UrlParameter.Optional } // Parameter defaults
);
It will build the URL in the fashion you're wanting.
(Alternatively, you can rename the parameter to your GetOrderDetails action to string OrderId and it will find the route that formats the URL the way you want it.)
As far as your main question:
How do I 'dynamically' load content on the page based on clicks to links?
There are two ways to approach this:
Post back pages.
AJAX / Dynamic loading of data and elements in the HTML on your page.
In the post-back scenario:
In this scenario your links would all go to actions that build a model that includes the orderlist from your main page, and for the details of the specific order you clicked you'd populate your model with specifics for that order. Then your ActionResult return is the same view (or one that looks the same at least), and your view would use the PartialView Html helper to render the details.
OrderViewModel:
public class OrderViewModel
{
public IList<Order> Orders {get;set;}
public OrderDetail Details {get;set;}
}
OrderView.aspx:
<%# Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<OrderViewModel>" %>
<%:Html.DisplayFor(m=>m.Orders)%> <%-- Displays the Table above listing orders --%>
<%:Html.DisplayFor(m=>m.Details)%> <%-- Displays your custom view of the details --%>
OrderController:
...
public ActionResult List()
{
var model = new OrderViewModel { Orders = GetAllOrders(), Details = null };
return View("OrderView", model);
}
public ActionResult GetOrderDetails(string OrderId)
{
var model = new OrderViewModel { Orders = GetAllOrders(), Details = GetOrder(OrderId) };
return View("OrderView", model);
}
...
In the Ajax scenario:
The Ajax scenario is essentially the same except that you hide the server round-trip in an ajax call, and then reload the page, or just a div with the content you want from the html (or JSON) in the return data of the ajax call.
The advantage of the Ajax approach is that you could specify a different Action on a different Controller for the various parts of the page you wanted to update.

Nima,
you can do it via partial views or render action, and json to display data
the basic example is as example here:
http://www.asp.net/mvc/tutorials/iteration-7-add-ajax-functionality-cs
or very popular option is display action for the task in jquery.dialog()
depends on you what way you want to proceed
cpo
revised:
My bad.
From logic point of view, it is as this:
It depends only on you, which way you want to go.
(From my point of view)
Benefits of separating the logic is :
simple to understand as controller is related only to actions for eg: orders
Can be used on more places if you need
Easy to test only small items, eg one testcase/fixture to controller for only orders
Usefull for more complicated projects
On the other hand
Keep everything in one controller and split the logic by regions
Eveything is together, easy to see other methods and what they do
Hope this is what you were looking for
cpo

Related

How to remain/retain on the same page when using PagedList.mvc

I am using PagedList.Mvc and I have added a nice way to navigate across various pages in a mvc web application. However, when I click on an "edit" or "details" tab and save changes I am sent back to the 1st page. I want to remain on the same page where the changes were made.
Here is the code I have in the controller:
// GET: Item
public ActionResult Index(int? page)
{
var items = db.Items.Include(i => i.PurchaseOrder);
return View(items.ToList().ToPagedList(page ?? 1, 3));
}
Here is the code I have in the view:
#using PagedList;
#using PagedList.Mvc;
#model IPagedList<PurchaseOrders.Models.Item>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.First().ItemDescription)
</th>
<th>
#Html.DisplayNameFor(model => model.First().Quantity)
</th>
<th>
#Html.DisplayNameFor(model => model.First().Price)
</th>
<th>
#Html.DisplayNameFor(model => model.First().DueDate)
</th>
<th>
#Html.DisplayNameFor(model => model.First().DateReceived)
</th>
<th>
#Html.DisplayNameFor(model => model.First().Comments)
</th>
<th>
#Html.DisplayNameFor(model => model.First().PurchaseOrder.PurchaseRequest_)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ItemDescription)
</td>
<td>
#Html.DisplayFor(modelItem => item.Quantity)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.DisplayFor(modelItem => item.DueDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateReceived)
</td>
<td>
#Html.DisplayFor(modelItem => item.Comments)
</td>
<td>
#Html.DisplayFor(modelItem => item.PurchaseOrder.PurchaseRequest_)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ItemId }) |
#Html.ActionLink("Details", "Details", new { id=item.ItemId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ItemId })
</td>
</tr>
}
</table>
#Html.PagedListPager(Model, page => Url.Action("Index", new { page }))
Please help!
You could pass an additional 'page` parameter to your edit method, for example
In your Index method, add
ViewBag.CurrentPage = page; // or use a view model property
Then your link would be
#Html.ActionLink("Edit", "Edit", new { id=item.ItemId, page = ViewBag.CurrentPage})
Then your edit method
[HttpGet]
public ActionResult Edit(int ID, int page)
{
ViewBag.CurrentPage = page; // pass current page to edit view
And your edit view
#using (Html.BeginForm(new { page = ViewBag.CurrentPage })) {
And in you post method
[HttpGet]
public ActionResult Edit(EditModel model, int page)
{
.... // Save
return RedirectToAction("Index", new { page = page });
In this case the page is stored in the ViewBag which makes it ephemeral (the ViewBag is only available for the current request).
In the controller, you're telling it if you get null use 1 as your current page. so null is always retuned and you get the 1st page everytime.
You need to provide the current page Number to your views that you navigate to (Edit/Create) and then provide it back to the original page when you're done.
You can use the TempData,that works well on HTTP redirects and lives longer than viewbag or viewData.
You can also move it arround with your models when calling actions and then give it back to the index action that needs a page number.
You can use sessions too. BTW, TempData is using session behind the scenes.
UPDATED:
Code to add in your index action:
var page = TempData["page"];
Code to add in the Create or Edit Submit action
//Get the page number
var page = TempData["page"];
//Set it back to Tempdata (because Tempdata is only for redirects) otherwise it will be lost
TempData["page"]=page;
add the value of the parameter to TempData["page"] when calling back the index action again
You can also access it from Index action directly since we repopulated it:
var page = TempData["page"];
return View(items.ToList().ToPagedList(page ?? 1, 3));
I also had this problem.
I tried to put it in the URL at first but it seems a bit weird to have ?page=2 in our URL.
So I replaced it with using TempData
What you need to do is this:
Store the page in TempData when you are in your Index() action method;
public const string PAGE_QUERY_STRING_KEY = "page";
public ActionResult Index(int page = 1)
{
TempData[PAGE_QUERY_STRING_KEY] = page;
...
}
Then use TempData.Peek(), instead of TempData[], everywhere else (to retain the value of your page between requests which are related to your current Index page) --- in your Edit, Create, Details, etc. action methods:
public ActionResult Edit(...)
{
...
return RedirectToAction(nameof(Index), new { page = TempData.Peek(PAGE_QUERY_STRING_KEY) });
// do not do this because this will remove the temp data
// return RedirectToAction(nameof(Index), new { page = TempData[PAGE_QUERY_STRING_KEY])
}
... and in your views:
<!--(Edit.cshtml)-->
...
<p>
#Html.ActionLink("Back to List", "Index",
new { page = TempData.Peek(FLP.Web.Controllers.UsersAdminController.PAGE_QUERY_STRING_KEY) })
</p>

How to add Edit, Delete and Search functionality in single view in MVC?

I'm new to MVC.
on MSDN i've studied that there should be folder in view with the same name of controller. For every Action Method in the controller we have to create a View in the same folder.
I'm creating a test application in which:
I have a homeController with an Index ActionMethod. Corresponding to it i have a View in View/home/Index, which simply show the listing of the employees.
I know i can add a [HTTP POST] Index ActionMethod in the homeController.
But i want to add the Delete and Search functionality on the view. So that a user can search the employees with there name and can delete an employee on the same page.
I don't know how can i move ahead for this functionality.
Still i'm using this code.
homeController
public ActionResult Index()
{
ViewBag.text = "Records Listing";
var q = from p in objEmp.tbemployees select p;
return View(q);
}
Index.cshtml
#model IEnumerable<MvcApplication6.Models.tbemployee>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>#ViewBag.text</h1>
<table style="font-size:15px;">
<tr>
<th>
Name
</th>
<th>
Address
</th>
<th>
Sallary
</th>
</tr>
#foreach (var item in Model)
{
<tr >
<td style="padding:7px;">
#Html.DisplayFor(mm => item.ename)
</td>
<td style="padding:7px;">
#Html.DisplayFor(mm => item.eadd)
</td>
<td style="padding:7px;">
#Html.DisplayFor(mm => item.esal)
</td>
<td style="padding:7px; color:Blue; text-decoration:underline;">
#Html.ActionLink("Edit", "Edit", new { id = item.empno })
</td>
</tr>
}
</table>
Thanks.
For the Delete you could add a column in the table that will invoke a controller action and pass it the current record id:
<tr>
<td style="padding:7px;">
#Html.DisplayFor(mm => item.ename)
</td>
<td style="padding:7px;">
#Html.DisplayFor(mm => item.eadd)
</td>
<td style="padding:7px;">
#Html.DisplayFor(mm => item.esal)
</td>
<td style="padding:7px; color:Blue; text-decoration:underline;">
#Html.ActionLink("Delete", "Delete", new { id = item.empno })
#Html.ActionLink("Edit", "Edit", new { id = item.empno })
</td>
</tr>
and your Delete action:
public ActionResult Delete(int id)
{
... use the passed id to delete the record from the database
return RedirectToAction("Index");
}
for the Edit functionality you could have a controller action that will fetch the record and render a view that will allow for editing:
public ActionResult Edit(int id)
{
var employee = objEmp.tbemployees.FirstOrDefault(x => x.Id == id);
if (employee == null)
{
// no employee with the specified id was found
return new HttpNotFound();
}
return View(employee);
}
and then you could have a corresponding ~/Views/Home/Edit.cshtml view:
#model Employee
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(x => x.ename)
#Html.EditorFor(x => x.ename)
</div>
<div>
#Html.LabelFor(x => x.eadd)
#Html.EditorFor(x => x.eadd)
</div>
...
<button type="submit">Save</button>
}
and of course a corresponding action to update the record when this form is submitted:
[HttpPost]
public ActionResult Edit(Employee employee)
{
... update the employee record
return RedirectToAction("Index");
}
You can add and implement a Delete action method in your controller. Then in your view, call #Html.ActionLink("Delete", "Delete", new { id = item.empno }). This will return a hyperlink which links to your Delete method in the controller.

Calling PostMethod from HTML.Actionlink

Hi I am fairly new to MVC and facing a issue.
I have a View which lists all the countries having just 2 columns
I want column headers clickable and should sort on clicking on it
I have shown my Controller & view code below and I expect that when I click on the column header it should hit Index action method decorated with [HttpPost]
When I click the header link page just refreshes without hitting Action method I expect it to hit
Any help would be appreciated.
Here is my controller code
[HttpPost]
public ActionResult Index(string sortcolumn)
{
return View(SortedList(sortcolumn));
}
private List<Country> SortedList(string sortcol)
{
List<Country> sortedlist = new List<Country>();
switch (sortcol)
{
case "idCountry":
if ((SortOrder)ViewData["sortorder"] == SortOrder.Ascending)
{
sortedlist = db.Countries.OrderByDescending(c => c.idCountry).ToList<Country>();
ViewData["sortorder"] = SortOrder.Descending;
}
else
{
sortedlist = db.Countries.OrderBy(c => c.idCountry).ToList<Country>();
ViewData["sortorder"] = SortOrder.Ascending;
}
break;
case "Countryname":
if ((SortOrder)ViewData["sortorder"] == SortOrder.Ascending)
{
sortedlist = db.Countries.OrderByDescending(c => c.Countryname).ToList<Country>();
ViewData["sortorder"] = SortOrder.Descending;
}
else
{
sortedlist = db.Countries.OrderBy(c => c.Countryname).ToList<Country>();
ViewData["sortorder"] = SortOrder.Ascending;
}
break;
}
return sortedlist;
}
Here is my view
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<eduSmart.Data.Entities.Country>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Index
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>
List of Countries</h2>
<p>
Manage list of countries on this page. You can choose your action creating, editing,
removing the country data.
</p>
<% using (Html.BeginForm("Index","Country")) { %>
Total Countries : <%: Model.Count() %>
<table>
<tr>
<th>
<%: Html.ActionLink("CountryID","Index",new { sortcolumn = "CountryID" }) %>
</th>
<th>
<%: Html.ActionLink("CountryName ", "Index", new { sortcolumn = "CountryName" })%>
</th>
<th>
</th>
</tr>
<% if (Model != null)
{ %>
<% foreach (var item in Model)
{ %>
<tr>
<td>
<%: item.idCountry%>
</td>
<td>
<%: item.Countryname%>
</td>
<td>
<%: Html.ActionLink("Edit", "Edit", new { id = item.idCountry })%>
|
<%: Html.ActionLink("Details", "Details", new { id = item.idCountry })%>
|
<%: Html.ActionLink("Delete", "Delete", new { id = item.idCountry })%>
</td>
</tr>
<% }
}%>
</table>
<%} %>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
</asp:Content>
You can't hit a post method with an Action link. One thing you could do, if all you're doing is sorting here, is change your post method to a get and change the name
Instead of
[HttpPost]
public ActionResult Index(string sortcolumn)
Have something like
public ActionResult Sort (string sortColumn)
And point your actionlink to Sort.

Accepting A IENUMERABLE model post in a controller in mvc 3 vb.net?

I have a view in my app that uses a #modeltype ienumerable of (xxxxxxx.abc), and uses a for each loop to populate the view. This view has select boxes that show up next to each item in the view. When I post the form to the controller accepting it as a formcollection does not work, and if I accept it like: ByVal abc as abc it says that its an invalid model.. The code is as follows:
<AcceptVerbs(HttpVerbs.Post)>
Function ClassAttendance(ByVal Attendance As Attendance) As ActionResult
If ModelState.IsValid Then
UpdateModel(Attendance)
db.SaveChanges()
Return RedirectToAction("Index")
End If
Return View()
End Function
Any ideas?? Can I somehow use a for each loop in the view without making it ienumerable? If so when It posts to the controller my below code would just about work.. The only value that really matters is the selectlist choice and the id of the record that it was changed for...
The view is:
#ModelTYPE List(Of xxxxx.attendance)
#Code
ViewData("Title") = "Class Attendance Record"
End Code
#Using Html.BeginForm
#<fieldset>
<table>
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Registrant ID
</th>
<th>
Course Status
</th>
<th>
Comments
</th>
</tr>
#For r As Integer = 0 To ViewBag.count
Dim i As Integer = r
#Html.HiddenFor(Function(m) m(i).id)
#<tr>
<td>
#Html.DisplayFor(Function(m) m(i).firstName)
</td>
<td>
#Html.DisplayFor(Function(m) m(i).lastName)
</td>
<td>
#Html.DisplayFor(Function(m) m(i).reg_id)
</td>
<td>
#Html.DisplayFor(Function(m) m(i).Completed_Class)
</td>
<td>
#Html.DropDownList("Completed_Class", New SelectList(ViewBag.courseStatus, "Status", "Status"))
</td>
<td>
#Html.TextBoxFor(Function(m) m(i).Comments, New With {.class = "AttenComment"})
</td>
</tr>
Next
</table>
<p>
<input type="submit" name="submit" />
</p>
</fieldset>
End Using
I have been over countless tut's and posts with no luck at all... I only want to update the model record for each record to the corresponding selected value from the selectlist... Thanks greatly for any and all help..
In brief, this can be done. There are many ways to accomplish this, the easiest by far I found was to have a custom view model which contains an array of the model you want to bulk insert.
public class MultipleAttendance
{
public Attendance[] attendances {get;set;}
}
Then in your View you can loop as such:
#for(int i=0,i<10;i++)
{
#Html.TextBox(attendances[i].firstName)
}
In the controller
[HttpPost]
public ActionResult Create(MultipleAttendance model)
{
// Get a value
model.attendances[0].firstName;
}
Hope it helps :)

Need advice before I develop a bad habit

I have a controller called AuctionsController. In it I have Actions called Index() and AuctionCategoryListing():
//Used for displaying all auctions.
public ActionResult Index()
{
AuctionRepository auctionRepo = new AuctionRepository();
var auctions = auctionRepo.FindAllAuctions();
return View(auctions);
}
//Used for displaying auctions for a single category.
public ActionResult AuctionCategoryListing(string categoryName)
{
AuctionRepository auctionRepo = new AuctionRepository();
var auctions = auctionRepo.FindAllAuctions()
.Where(c => c.Subcategory.Category.Name == categoryName);
return View("Index", auctions);
}
As you can tell, they both invoke the same View (is this action called 'to invoke a view'. What is it's proper name?).
#model IEnumerable<Cumavi.Models.Auction>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th></th>
<th>
IDSubcategory
</th>
<th>
IDCity
</th>
<th>
IDPerson
</th>
<th>
Title
</th>
<th>
TextBody
</th>
<th>
ContactNumber
</th>
<th>
AskingPrice
</th>
<th>
AddressDirection
</th>
<th>
LatestUpdateDate
</th>
<th>
VisitCount
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
<td>
#item.IDSubcategory
</td>
<td>
#item.IDCity
</td>
<td>
#item.IDPerson
</td>
<td>
#item.Title
</td>
<td>
#item.TextBody
</td>
<td>
#item.ContactNumber
</td>
<td>
#String.Format("{0:F}", item.AskingPrice)
</td>
<td>
#item.AddressDirection
</td>
<td>
#String.Format("{0:g}", item.LatestUpdateDate)
</td>
<td>
#item.VisitCount
</td>
</tr>
}
</table>
They both inherit from the same Model.
My question is, am I doing things the right appropriate way? Or is this just a hack I managed to scrape together. Help me before I learn a bad habit.
I'd modify this to:
public ActionResult Index(string categoryName)
{
AuctionRepository auctionRepo = new AuctionRepository();
var auctions=auctionRepo.FindAllAuctions();
if (!string.IsNullOrEmpty(categoryName))
{
auctions = auctions.Where(c => c.Subcategory.Category.Name == categoryName);
}
return View(auctions);
}
Your route might then look like:
context.MapRoute(
"auction_defalt",
"Auction/{categoryName}",
new { controller="Auction", action = "Index", categoryName = UrlParameter.Optional }
Since the actions are so similar, I don't see a reason to separate them.
Like any framework ASP.NET MVC gives you plenty of opportunities to shoot yourself in the foot. Without forethought the reuse of controller actions, view models, and views can quickly become a maintenance nightmare. Not to mention that without similar consideration your routes will become hard to tie together.
Following the tenets of convention over configuration you could solve your problem by using separate actions but reusing a view partial. To me the index action of the AuctionsController should be responsible for listing all Auctions in the system. I wouldn't call my category action AuctionCategoryListing, but would instead call it simply Category. Through convention this has the nice effect of laying out the routes as:
site.com/auctions/ for the index
site.com/auctions/category/CATEGORYNAME for the category.
The route is easily understandable by the user and easy for you to understand explicitly what each does. (To this point Omar provides a good suggestion in his answer to let your repository handle pagination, filtering etc.)
As far as what each action should return you have several options. My preference would be to return separate views each containing a reference to a common partial. This gives you flexibility to create different views surrounding the partial but provides reuse for the piece that is common.
Further reading that might be of help:
One ViewModel per View
ASP.NET MVC terminology is tripping me up - why 'ViewModel'?
when should i use partial views in asp.net mvc?
You have to do branching somewhere, so it's probably more of a preference question.
The way I would handle it is to have a single method, and have it take in the category name as the parameter. Since strings are nullable, if one is not specified it will be null. My one action method would probably look something like:
public ActionResult Index(string categoryName)
{
AuctionRepository auctionRepo = new AuctionRepository();
var auctions = auctionRepo.FindAllAuctions();
if(String.IsNullOrEmpty(categoryName) == false)
auctions = auctions.Where(c => c.Subcategory.Category.Name == categoryName);
return View(auctions);
}
I would prefer the repo to do things like filtering and pagination for the sake of performance and DRY concept
public ActionResult Index(string categoryName)
{
AuctionRepository auctionRepo = new AuctionRepository();
//Let the Repo Handle things like filtering and pagination, avoiding performance issues
var auctions = auctionRepo.FindAllAuctions(categoryName);
return View(auctions);
}
DAL should be responsible for this tasks.
It's a feature of MVC that the view and controller are independent. You could equally use shared or partial views for the same thing, if anything I'd say it's a good thing because you're writing re-usable code and making use of it.

Resources