Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep controllers small in ASP.NET MVC?

I have a pretty well designed architecture where controllers go to services which access repositories which communicate with the database.

As such, logic in controllers is kept at a minimum, but I still have very subtle pieces of code that perform some tasks like

  • validate the model
  • arrange the action method arguments
  • invoke some service with these arguments, maybe validate the result and return the view if the model is now invalid
  • finally produce a model from the service's result, and return that.

some longer cases do different things depending on a "status" returned by the service.

here's a couple of examples:

[HttpPost]
[AjaxOnly]
[Authorize]
public JsonResult Preview(string input)
{
    LinkResult parsed = linkService.ParseUserInput(input);
    if (parsed.Result == LinkParseResult.Used)
    {
        long? postId = parsed.Link.PostId;
        if (postId.HasValue)
        {
            Post post = postService.GetById(postId.Value, false);
            return Json(new
            {
                faulted = "used",
                link = DetailsRoute(post),
                id = postId
            });
        }
        else
        {
            return Json(new { faulted = "invalid" });
        }
    }
    else if (parsed.Result == LinkParseResult.Invalid)
    {
        return Json(new { faulted = "invalid" });
    }
    else
    {
        Link link = parsed.Link;
        if (link.Description != null && link.Description.Length > 200)
        {
            link.Description = link.Description.Substring(0, 200);
        }
        return AjaxView(link);
    }
}

and (Post comes from domain, PostModel is the view model)

private PostModel PostModelConverter(Post post)
{
    Link link = post.Link;
    if (link == null)
    {
        throw new ArgumentException("post.Link can't be null");
    }
    if (link.Type == LinkType.Html)
    {
        return new PostedLinkModel
        {
            Description = link.Description,
            PictureUrl = link.Picture,
            PostId = post.Id,
            PostSlug = postService.GetTitleSlug(post),
            Timestamp = post.Created,
            Title = link.Title,
            UserMessage = post.UserMessage,
            UserDisplayName = post.User.DisplayName
        };
    }
    else if (link.Type == LinkType.Image)
    {
        return new PostedImageModel
        {
            PictureUrl = link.Picture,
            PostId = post.Id,
            PostSlug = postService.GetTitleSlug(post),
            Timestamp = post.Created,
            UserMessage = post.UserMessage,
            UserDisplayName = post.User.DisplayName
        };
    }
    return null;
}

this raises the question about if view models really should be in the web project as a rule, or they could actual be part of the domain, or some other project.

I'm not sure I can do much about the preview action, other than maybe use a PreviewModel that receives the Link, and truncates the description, but that would save up like, two lines.

The model converter should probably be somewhere else, but I'm clueless as to where that should be.

Another point that comes to mind is if I should be splitting this controller either using the partial keyword (is it a bad practice to use this for something else than autogenerated classes?), or adding routes that use different controllers depending on what action is requested or what http method is being used, what's the usual way to handle that?

like image 310
bevacqua Avatar asked Jul 31 '12 20:07

bevacqua


People also ask

Can partial view have controller?

It does not require to have a controller action method to call it. Partial view data is dependent of parent model. Caching is not possible as it is tightly bound with parent view (controller action method) and parent's model.

Can one view have multiple controllers?

Yes, It is possible to share a view across multiple controllers by putting a view into the shared folder. By doing like this, you can automatically make the view available across multiple controllers.

Can we have multiple controllers in MVC?

In Spring MVC, we can create multiple controllers at a time. It is required to map each controller class with @Controller annotation.


1 Answers

This has been asked several times:
Business logic in the controller
Where should I put my controller business logic in MVC3
Keep Controllers Thin

As well as written about elsewhere:
ASP MVC Best Practices - Skinny Controllers
Keep Controllers Thin

The community seems to be at a good consensus that this kind of logic belongs outside the controllers. Generally in the model (or ViewModel), but somewhere in the business layer.

As a final note, using partials for non-autogenerated code is not discouraged. If it makes sense to split things, do so. Just think about about what your reasons for splitting it are. This is going to be a case-by-case kind of thing.

like image 88
Kyeotic Avatar answered Oct 23 '22 09:10

Kyeotic