Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

Controller para Views Shared

Quero exibir todas as categorias cadastradas no menu do site que fica no arquivo "_Topo" da pasta "Shared" e todas as noticias na view "Index" da pasta Home. A view "_Topo" e importada em todas as paginas do site, entao estou tendo dificuldade para fazer isso funcionar. Estou usando uma ViewModel mas ta me voltando o erro generico quando faco o @foreach (var cat in Model.Categorias) "Object reference not set to an instance of an object." Seguem os codigos do controller da Shared:

namespace Blog.Areas.Paginas_Blog.Controllers
{
    public class SharedController : Controller
    {
        private CategoriaDAO categoriaDAO;


        public SharedController(CategoriaDAO categoriaDAO)
        {
            this.categoriaDAO = categoriaDAO;
        }

        public ActionResult _Topo(DefaultModel model)
        {
            model.Categorias = categoriaDAO.Lista();
            return View("~/Areas/Paginas_Blog/Views/Shared/_Topo.cshtml", model);
        }
    }
}

Codigo da view _Topo:

@model Blog.Areas.Paginas_Blog.Models.DefaultModel 
  <ul class="dropdown-menu" aria-labelledby="about-us">
                     @foreach (var cat in Model.Categorias)
                     {
                          <li><a href="#">@cat.Nome</a></li>
                      }
   </ul>

E por fim minha ViewModel:


namespace Blog.Areas.Paginas_Blog.Models
{
    public class DefaultModel
    {
        public IList<Noticia> Noticias { get; set; }

        public IList<Categoria> Categorias { get; set; }
    }
}
6 respostas

Olá Lucas,

se o seu _Topo aparece em todas as páginas, então provavelmente ele está sendo importado na _Layout. Você chamou o _Topo usando o método @Html.Partial? O problema é que este método simplesmente devolve um cshtml que esteja em Views/Shared, ou seja, ele não bate no seu Controller. Para chamar um controller a partir da sua view, você precisa usar o método @Html.Action

Lucas, deu certo, mas agora volta o seguinte erro: "A public action method '_Topo' was not found on controller 'Blog.Areas.Paginas_Blog.Controllers.HomeController'." O controller que estou usando e o SharedController, mas esta tentando achar o method "_Topo" no HomeController. Saberia o que posso fazer para ele procurar o method la no SharedController e nao no Home ? Pois queria mante-los em controllers separados para maior organizacao. Obrigado.

Investigando aqui, o problema é que você não pode ter uma SharedController.

Uma coisa que a gente faz bastante quando vamos trabalhar com um menu desses é criar o MenuController para ter esta responsabilidade. E chamá-lo com o @Html.Action. Se fizer questão de deixar o _Topo na Shared, o seu método no MenuController pode retornar uma view para ~/Views/Shared/_Topo.

Mudei o controller para MenuController em vez de SharedController e o erro persiste. Codigo do MenuController:


    public class MenuController : Controller
    {
        private CategoriaDAO categoriaDAO;

        public MenuController(CategoriaDAO categoriaDAO)
        {
            this.categoriaDAO = categoriaDAO;
        }
        // GET: Paginas_Blog/Menu
        public ActionResult Index(DefaultModel model)
        {
            model.Categorias = categoriaDAO.Lista();
            return View("~/Areas/Paginas_Blog/Views/Shared/_Topo.cshtml", model);
        }
    }

Como estou chamando a shared view "_Topo" no _Layout.cshtml:

@Html.Action("Index", "Menu")
solução!

Valeu Lucas. Resolvi vendo a 2 aula do curso de Razor.

Quando você colocar o ~ ele já coloca na raiz do projeto, ou seja, ele começa a olhar a partir do Paginas_Blog. Então para achar o cshtml deveria ser ~/Views/Shared/_Topo.cshtml