Duplicating code in MVC controllers

I think I have a problem in understanding the proper way of using MVC. The problem I'm having is that I have Users and Admin Users, both are allowed to create a campaign but they are using different master pages etc etc.

My solution so far is...

Controllers
    AdminUserController.cs
    UserController.cs

Views
    AdminUser
        CreateCampaign.aspx
    User
        CreateCampaign.aspx

But in doing it in this way I'm having to duplicate the CreateCampaign() code in both the AdminUserController and the UserController and I have 2 views to do the same thing.

Is this the right way of doing it or am I missing the boat somewhere?

Upvotes: 4

Views: 842

Answers (6)

John Foster
John Foster

Reputation: 8755

If it's as simple as displaying a different master to users who are admins you can set the master page to use for the View from the controller as follows:-

return View("CreateCampaign", User.IsInRole("Admin") ? "Admin", "User");

This should allow you to have a single Campaign controller and Create view which seems more natural to me than controllers dedicated to a particular type of user (which sounds like an implementation detail).

Upvotes: 0

David Glenn
David Glenn

Reputation: 24522

How about having a CampaignController that has the Create method which then displays different views depending on the type of user. Something like:

public class CampaignController : Controller {

  public ActionResult Create() {
    //...
    if (User.IsInRole("Admin") {
      Return View("AdminUser/CreateCampaign");
    }
    else {
      Return View("User/CreateCampaign");
    }
  }

}

And as others have said the duplicated markup/code in the views should be seperated into partial views and then RenderPartial() used:

<% Html.RenderPartial("Campaign") %>

Upvotes: 0

tvanfosson
tvanfosson

Reputation: 532465

Extract the common code to a base controller from which both inherit. Extract the shared view to a common, shared partial view (ViewUserControl), then have each view include this shared partial. The latter is really only necessary since your view uses different master pages.

Controllers:

BaseUserController
    CreateCampaign()

UserController : BaseUserController
AdminController : BaseUserController

Views:

Shared
   CreateCampaignShared.ascx
   Admin.Master
   User.Master
Admin
   CreateCampaign.aspx  -- includes <% Html.RenderPartial( "CreateCampaignShared" ); %>
User
   CreateCampaign.aspx  -- includes <% Html.RenderPartial( "CreateCampaignShared" ); %>

Upvotes: 9

womp
womp

Reputation: 116977

You're missing the partial boat :)

You can create one CreateCampaign.ascx file that shares the common view code and call it as a partial view in some other view. Instead of creating full views, create a partial view (an .ascx file), and have it contain the duplicate code and markup.

Then you can re-use it in other views with this:

<% Html.RenderPartial("CreateCampaign") %>

Re-use your controller code by factoring it out into some base controller which your specific controllers inherit from.

Upvotes: 0

griti
griti

Reputation: 650

Why do you have two different "Users"? I'd prefer one user-Class and roles to provide access to different views / actions

Then you would create a Campain-Controller and there a CreateCampaign-Action.

Upvotes: 1

user151323
user151323

Reputation:

You can do pretty well with a single controller, leave it to UserController. Admin is just another user, right? In your CreateCampaign() code you can check for "special" status of the logged in user and set some extra properties before saving the data.

Whether you can get away with a shared view depends on how much they vary. You can use simple IsAdmin() checks in the view to render or not some extra controls. Or you can check it in the controller and serve one view or another.

Upvotes: 2

Related Questions