0

i'm working on a mvc project and i want to display a sponsorimage on each page.

But i'm having difficulties with showing them into the shared layout page that is rendered on with each view.

I've created a function in my Domain service class where i search the student's school, because the school is linked to a country, not the student. When i got that countryId, i search through the countries of each Advert where the countryId is equal to the school's countryId. When that's the case, i look for the sponsor of that particular advert, put them into a SponsorList, select a random sponsor from that SponsorList and return the SponsorCompany (because i renamed each sponsorimage to the companyname).

Now i want to call that function into the shared layout, so every time the pages renders, a random sponsorimage is showed for that particular student. But i dont know how to call that function because shared layout has no controller class.

    public String advertsForCountry()
{
    String studentSchool = finder.getLoggedStudent().SchoolId;
    int studentCountry = db.Schools.Find(studentSchool).CountryId;

    List<Sponsor> sponsorsForStudent = new List<Sponsor>();
    List<Advert> adverts = db.Adverts.ToList();
    foreach(Advert adv in adverts)
    {
        foreach(Country cntry in adv.Countries)
        {
            if(cntry.CountryId == studentCountry)
            {
                sponsorsForStudent.Add(adv.Sponsor);
            }
        }
    }
    Random random = new Random();
    int randomSP = random.Next(0, sponsorsForStudent.Count()-1);
    string sponsorAdvert = sponsorsForStudent.ElementAt(randomSP).SponsorCompany;
    return sponsorAdvert;       
}

Sorry English is not my native language.

Ant P
  • 24,820
  • 5
  • 68
  • 105
Gijs
  • 885
  • 2
  • 13
  • 22
  • Consider making a child action. – SLaks Jun 03 '13 at 20:24
  • My suggestion would to forget about the `static method` because it's not a correct `MVC` pattern the logic of business model should not be in a `View`. Create a `ViewModel` then return a simple `PartialView` bound to that `ViewModel`. – hackp0int Jun 03 '13 at 20:27

2 Answers2

0

Create a controller action that returns a partial view.

public PartialViewResult SponsoredAdvert()
{
    var model = new SponsoredAdverModel();
    model.AdvertText = _domainService.advertsForCountry();
    return PartialView("myView", model);
}

Place the method in a suitable controller (HomeController would make sense given that this is for your Layout.cshtml) and use RenderAction in your view:

@Html.RenderAction("MyAction", "MyController")

As you can see, RenderAction allows you to specify the controller, which means that you can use this within your Layout.cshtml even though it, in itself, is not associated with a specific controller.

Ant P
  • 24,820
  • 5
  • 68
  • 105
  • I'm not calling the method in the homecontroller view, but in the shared _layout.cshtm view. This contains my navigation bar etc and has no controller. If i put it in the homecontroller, this wil only be working on the homepage. – Gijs Jun 03 '13 at 21:19
  • No, it won't. As I described in my answer, `RenderAction` takes a `controller` parameter which allows you to specify which controller class contains the action method `MyAction`. You can use it to render PartialViewResults from any controller into any view - including from Layout.cshtml. – Ant P Jun 03 '13 at 21:21
0

To expand upon @SLaks suggestion;

Create an action that is marked with a ChildActionOnlyAttribute (this prevents it from being called via a regular HTTP request). Here's an example from my website:

[HttpGet]
[ChildActionOnly]
public ActionResult RandomQuote()
{
    var model = _services.GetRandomQuote();

    return PartialView("_QuoteOfTheMomentWidget", model);
}

This child action gets called in the _Layout via a simple @Html.Action("randomquote").

Tieson T.
  • 20,774
  • 6
  • 77
  • 92
  • But in which controller you put the code? Because _Layout.cshtml has no controller. – Gijs Jun 03 '13 at 22:18
  • @Gijs Any controller works. For instance, the one I posted assumes the action is defined in the Home controller, and that a `_QuoteOfTheMoment.cshtml` view exists in either the `home` or `shared` folder. If it was in, say, `WidgetsController`, the call gets adjusted to `@Html.Action("randomquote", "widgets")`. – Tieson T. Jun 03 '13 at 22:54
  • i'm implementing your solution but get the error '{"The controller for path '/' was not found or does not implement IController."}' I thought i found the solution here: http://stackoverflow.com/questions/14011026/the-controller-for-path-was-not-found-or-does-not-implement-icontroller But i'm not working with these area's, this funtion has to work for everyone. – Gijs Jun 04 '13 at 08:59
  • @Gijs Post what you're trying to use - it sounds like you're using the incorrect syntax for the view parameter. – Tieson T. Jun 04 '13 at 21:46