开发者

how to reference controller function from another controller

Trying to learn ASP MVC coming from Linux/LAMP background (in other words I'm a newb) ...

For some reason I can't seem to use a function defined in a controller in another controller.

Here's the function in my MessagesController.cs file:

    public List<Message> GetMessagesById(string username)
    {
        return db.Messages.Where(p => p.user == username).ToList();
    }

When I try to reference it:

    using LemonadeTrader.Models;
    using LemonadeTrader.Controllers;     // added this to pull the Messages::getMesssagesById
  开发者_JAVA技巧  ...

    ViewBag.messages = lemondb.Messages.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString());

I get something along the lines of lemondb.Messages does not contain a method called GetMesssagesById.

How do I reference it?


You shouldn't be linking controller methods like this, not to mention that controllers shouldn't be performing data access directly. I would recommend you externalizing this function into a separate class/repository which could be used by both controllers.

Example:

public class MessagesRepository
{
    public List<Message> GetMessagesById(string username)
    {
        return db.Messages.Where(p => p.user == username).ToList();
    }
}

and then:

public class FooController: Controller
{
    public ActionResult Index()
    {
        var db = new MessagesRepository()
        ViewBag.messages = db.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString());
        return View();
    }
}

public class BarController: Controller
{
    public ActionResult Index()
    {
        var db = new MessagesRepository()
        ViewBag.messages = db.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString());
        return View();
    }
}

OK, that's the first step. This code could be improved by decoupling the controllers from the repository by introducing an abstraction for this repository:

public interface IMessagesRepository
{
    List<Message> GetMessagesById(string username);
}

public class MessagesRepository: IMessagesRepository
{
    public List<Message> GetMessagesById(string username)
    {
        return db.Messages.Where(p => p.user == username).ToList();
    }
}

then you could use constructor injection for those controllers:

public class FooController: Controller
{
    private readonly IMessagesRepository _repository;
    public class FooController(IMessagesRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index()
    {
        ViewBag.messages = _repository.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString());
        return View();
    }
}

public class BarController: Controller
{
    private readonly IMessagesRepository _repository;
    public class BarController(IMessagesRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index()
    {
        ViewBag.messages = _repository.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString());
        return View();
    }
}

finally you would configure your DI framework to pass the corresponding implementation into those controllers.

I would also recommend you replacing this ViewBag with a strongly typed view model:

public class MyViewModel
{
    public List<Message> Messages { get; set; }
}

and then:

public ActionResult Index()
{
    var model = new MyViewModel
    {
        Messages = _repository.GetMessagesById(Membership.GetUser().ProviderUserKey.ToString())
    };
    return View(model);
}


Place GetMessageById (and all other methods needed for accessing messages) to separate class and use the class everywhere you need to get Message data.

MessageService service = new MessageService();
ViewBag.messages = service.GetMessagesById(...);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜