tags:

views:

44

answers:

3

I have a table of data which contains newsarticles.

ive created standard CRUD views/forms and it has paging too.

eg at the moment i have urls's like this:

// GET: /News/
//      /News/Page/2  

News articles can be archived (a boolean value in the db)

i want a url to map to only archived data in the db or non archived data.

eg /News/Archived/Page/2 should map to page 2 of only Archived items.

and /News/Page/2 should map to page 2 of non archived items.

what do i need to do in global asax to achieve this. and what should the signature of the index method be?

//Signature in controller
public ActionResult Index(int? page)


//Route for paging
 routes.MapRoute(
               "NewsArticles",
               "News/Page/{page}",
               new { controller = "News", action = "Index" }
           );
A: 
//Signature in controller
public ActionResult Archive(int? page)


//Route for paging
routes.MapRoute(
               "NewsArticles",
               "News/Archive/Page/{page}",
               new { controller = "News", action = "Archive", page = 1 }
);

I would probably also simplify the routes to not include the word page ie: "News/Archive/{page}" and "News/{page}" but this depends on what other routes you have.

Richard
A: 

If you want to use the same action on your controller for serving both situations, I'd probably change the signature to something like this:

public ActionResult Index(bool archive, int? page)

Then, you can have two different routes for this. First for the non-archived stuff:

routes.MapRoute(
    "NewsArticles",
    "News/Page/{page}",
    new { controller = "News", action = "Index", archive = false }
);

And then for the archive version:

routes.MapRoute(
    "NewsArticlesArchive",
    "News/Archive/Page/{page}",
    new { controller = "News", action = "Index", archive = true }
);

Now you have the liberty in your action of filtering based on the archive bool. Also, I agree with the others here that the Page text in the URL is redundant. If you decide to remove it, you can just yank it out the routes above and everything should still work. Good luck!

Scott Anderson
I recommend against using the same action method to control two different data paths. This tends to create more complex logic within the action method, which is advised against for best MVC patterns - the action method should be logic and error agnostic, and should just pass the parameters down into the domain, and pass whatever data is returned into a View (or return any errors from the domain (if any)).
eduncan911
I disagree. The Controller is in charge of communicating with the model and obtaining results. I don't see how this goes against the MVC pattern at all. The OP stated that the only distinguishing factor between archived and non-archived results is a single bit field in the database. I see no harm in passing this off to your model to toggle the results you get back.
Scott Anderson
Also, it's not two different "data paths" as you outlined above. In your solution, the OP would either have to create two Views, or pass the name of the View to the View() method, and in either case his model objects will be identical for both controller methods. It just seems like adding code for the sake of coding to me...
Scott Anderson
Hehe, yes. Great minds think... oppositely. I approach things from TDD/BDD, where I would design two methods - not knowing anything about the other method.
eduncan911
I do BDD, too (thank god for mspec, xunit, and Moq). I can see the value in having two methods, especially for the future should these two code paths diverge, but simply passing a bool to this action is pretty harmless to me :)
Scott Anderson
Exactly, "Technical Debt!" for the future.
eduncan911
Off-topic (eh, why not?): I just got ReSharper's unit tests wired up using MSpec, xUnit, and Moq yesterday. Man, I am in love. Think having a great Unit Test explorer, that organizes/groups your tests based on the MSpec namespace and [Subject()] declaration! Going to blog this today, as its just too sweet. No more Output or Html report viewing!
eduncan911
I'm new to mvc so not really qualified to comment. But i preferred this way as the other way seemed like a lot of duplication for what was a simple change in the end. I decided to go by DRY - Dont Repeat Yourself. Thank you to all that helped.
raklos
+1  A: 

First, I'd recommend getting rid of "/Page". It's not needed. You can default to the first page, and have it pass "1" to your 'Archived(int page)' and 'NonArchived(int page)' methods automatically. Also, if you want the word "/Page/" in your url, you are going to have to duplicate the maps below: one set without "/Page" in the url (as shown below), and another set with "/Page".

Note, MapRoute works in order. If you want /Page, then you have to have those two routes first (News/Archive/Page/{page} and News/Page), before you use the two urls below.

routes.MapRoute(
  "ArchivedArticles",
  "News/Archive/{page}",
  new { controller = "News", action = "Archived", page = 1 }
);

routes.MapRoute(
  "NonArchivedArticles",
  "News/{page}",
  new { controller = "News", action = "NonArchived", page = 1 }
);

If '/news/archive/' is used, page will equal 1. If '/news/archive/2' is used, then page will equal 2, and so on. Same for '/news' and '/news/2'.

Your NewsController would have two methods:

public class NewsController : Controller
{
  [AcceptVerbs(HttpVerbs.Get)]
  public ViewResult NonArchived(Int32 page)
  {
    ...
  }

  [AcceptVerbs(HttpVerbs.Get)]
  public ViewResult Archived(Int32 page)
  {
    ...
  }
}

You could actually skip the 2nd maproute above, if you use the default Index() route. The catch is you'd have to change the action method signature from "page" to "id" - and it will work. I just made it more verbose for more transparency by not using any assumptions from the mvc framework.

eduncan911
the suggestion for getting rid of `Page` in the URL makes sense to me, but if all he's doing is returning the same view with the same model objects based on a bit field, it really seems silly to have two controller methods. Why not consolidate into one and make the controller take another parameter like in the solution I posted?
Scott Anderson
Funny, I just replied to your question stating why not to use the same action method. Both action methods above can return the same View with the same format. To each his own I suppose. lol
eduncan911
Great minds think... oppositely? haha :)
Scott Anderson