tags:

views:

73

answers:

2

I having trouble getting a value to my base controller. All I would like to do is have my base contoller pick up a ID from an ActionLink?

Link

<%= Html.ActionLink("About Us", "About", new { SectionId = 1 })%>

Base Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Website.Controllers
{
    public class SectionController : Controller
    {
        //
        // GET: /Section/

        public SectionController(int SectionId)
        {
            if (SectionId == 1)
            {
                ViewData["Message"] = "GOT AN ID";
            }
            else
            {
                ViewData["Message"] = "NO ID";
            }
        }
    }
}

Home Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Website.Controllers
{
    [HandleError]
    public class HomeController : SectionController
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult About()
        {
            return View();
        }


        public ActionResult Contact()
        {
            return View();
        }

   }
}

Solution so far

ActionLink

<%= Html.ActionLink("About Us", "About", new { SectionId = 1})%>

SectionAttribute.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Website.ActionFilters
{
    public class SectionAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
        // Actions have sectionId parameter
        object SectionId = filterContext.ActionParameters.FirstOrDefault(x => x.Key == "SectionId").Value;

            if (SectionId != null && (int)SectionId == 1)
            {
                filterContext.Controller.ViewData["Message"] = "GOT AN ID";
            }
            else
            {
                filterContext.Controller.ViewData["Message"] = "NO ID";
            }
        }
    }
}

SectionController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Website.ActionFilters;

namespace Website.Controllers
{
    [Section]
    public class SectionController : Controller
    {
    }
}

View

<%= Html.Encode(ViewData["Message"]) %>
A: 

A constructor of a base controller is not typically the place where common code is placed. You usually create a filter for common code. If you decorate the base controller with this filter attribute, then all inheriting controllers use that filter.

Malcolm Frexner
I'm new to .net and mvc. How would I go about creating a filter?
Jemes
try this one http://www.asp.net/learn/mvc/tutorial-14-cs.aspx
Malcolm Frexner
+1  A: 

Your code won't work. Instead you should define OnActionExecuting method in base controller, where you get actual sectionId from route data and set ViewData accordingly. Try something like this (not tested):

public class SectionController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Actions have no sectionId parameter - look for it in querystring
        string SectionId = filterContext.HttpContext.Request.QueryString["sectionId"];

        int sId;

        if (int.TryParse(SectionId, out sId) && sID == 1)
        {
            filterContext.Controller.ViewData["Message"] = "GOT AN ID";
        }
        else
        {
            filterContext.Controller.ViewData["Message"] = "NO ID";
        }
    }
}

Updated:

You can move this out from controller and create ActionFilter. It is very simple:

public class SectionAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Actions have sectionId parameter
        object SectionId = filterContext.ActionParameters
            .FirstOrDefault(x => x.Key == "sectionId").Value;

        if (SectionId != null && (int)SectionID == 1)
        {
            filterContext.Controller.ViewData["Message"] = "GOT AN ID";
        }
        else
        {
            filterContext.Controller.ViewData["Message"] = "NO ID";
        }
    }
}

...

[Section]
public class SectionController : Controller {

or

[HandleError, Section]
public class HomeController : SectionController {
eu-ge-ne
+1 Still better is we can move this out from the base class and put it in an action-filter/attribute to make it more elegant ? Thanks
Mahesh Velaga
Thanks for the help. I'm trying the code but I'm getting the error below on the OnActionExecuting.Error 2 'Website.Controllers.SectionController.OnActionExecuting(System.Web.Mvc.ActionExecutingContext)': cannot change access modifiers when overriding 'protected' inherited member 'System.Web.Mvc.Controller.OnActionExecuting(System.Web.Mvc.ActionExecutingContext)'
Jemes
OnActionExecuted has protected modifier in controllers and public - in filters - I've fixed my answer
eu-ge-ne
I've not created an ActionFilter before so bare with me. Where should I save an ActionFilter class to? Also if my base controller inherits the section ActionFilter will that be available to all my views?
Jemes
Just create separate file SectionAttribute.cs and put the code there; Dont forget to add using Namespace.Of.SectionAttribute to your controllers; You can decorate base controller with this attribute and it will work for all inherited controllers
eu-ge-ne
Thanks for your help. I'm nearly there just getting one error on the SectionAttribute.cs file.Error 1 Operator '==' cannot be applied to operands of type 'object' and 'int'.I'll update my original question with the solution I've git so far.
Jemes
Why does SectionId need to be an object rather than a Var?I'm getting no errors but when I click my ActionLink I'm only getting "NO ID" on each page. So it's like its not picking up the ID?
Jemes
You have to add SectionId parameter to each Action or change `object SectionId = filterContext.RouteData.Values["sectionId"];` to `string SectionId = filterContext.HttpContext.Request.QueryString["sectionId"];`
eu-ge-ne
Thanks for the update but now I'm getting the error below on the updated code...The given key was not present in the dictionary.// Actions have SectionId parameterobject SectionId = filterContext.ActionParameters["SectionId"];
Jemes
Sorry, Jemes. I've updated the code again.
eu-ge-ne
No errors now but I'm still not picking up the ID as my views still say "NO ID"
Jemes