Override View() in asp.net mvc - asp.net-mvc

I have the follow base controller-
public abstract class BaseController : Controller
{
protected string BaseUrl = "URL";
}
All other controller inherit the above base controller-
public class MyController : BaseController
{
public ActionResult Something()
{
ViewBag.BaseUrl = base.BaseUrl;
return View();
}
}
I don't want to write ViewBag.BaseUrl = base.BaseUrl; in every controller action method. Rather, I would to automatically pass this base url to the related view. Is it possible by overriding View()?
An example would be better for me.

If all controllers derive this then just put it in here:
public abstract class BaseController : Controller
{
protected string BaseUrl = "URL";
public BaseController()
{
ViewBag.BaseUrl = base.BaseUrl;
}
}
I would even make it private if I do not want inheriting classes to overwrite it.

Related

MVC Routes data not available

I have a controller called BaseController. In the BaseController, I have an Action method called Index which has some logic that involves querying the routes and building the URLs. Something on the lines of:
var link = Url.RouteUrl("myroute", new { id = 5 });
All this is well and fine until I create a controller NewController that extends the BaseController. In the constructor of NewController, I pass BaseController as a dependency.
public class NewController
{
private BaseController _baseController;
public NewController(BaseController baseController)
{
_baseController = baseController;
}
public ActionResult Index()
{
return _baseController.Index();
}
}
Reason why this was needed was because I need to override the view (some HTML and CSS changes). I didn't want to recreate the models and services and rewrite the business logic, so thought this would be the best and most time-effective approach.
Only issue is when the BaseController's Index Action is called, the Url is null obviously. Routes data is not available because the request was generated outside the base controller.
What is the best way to get around this?
Make BaseController.Index() virtual:
public class BaseController : Controller
{
public virtual ActionResult Index()
{
return View();
}
}
Then use inheritance:
public class NewController : BaseController
{
public override ActionResult Index()
{
var index = base.Index();
//do whatever
return index;
}
}
You are trying to call action method from another controller. Propably your constructor method gets baseController as a null. can you try to implement it like following
public ActionResult Index()
{
return new BaseController().Index(); // assume you call index action
}
Or you can call BaseController action from another controller like following
public ActionResult Index()
{
return RedirectToAction("Index", "Base"); // assume you call index action
}
You can also change Route url like following.
#Url.RouteUrl("myroute", new { controller = "Base", action = "Index", id = 5 })
I have another solution that requires a little bit of code design efforts.
Why don't you Abstract your business logic away from the two Controllers?
For example: RouteBuilder.cs a class that have the functions that contains the logic of building the routes.
And BaseClass.cs is a class that contains the Logic shared between the two Controllers.
Then:
public class BaseController
{
public ActionResult Index()
{``
//Instantiase BaseClass.cs and call the needed functions. Then RouteBuilder.cs and call functions.
return View();
}
}
public class NewController
{
public ActionResult Index()
{``
//Instantiase BaseClass.cs and call the needed functions.
return View();
}
}
Viola. Problem solved and clean code produced.

Access controller level variable from action method attribute

I have the following base class for all controllers-
public abstract class BaseController:Controller
{
public string BaseUrl
{
get { return "something"; }
}
}
I also have the following action filter attribute-
public class CheckQueryStringAttribute : ActionFilterAttribute
{
string baseUrl;
public CheckQueryStringAttribute(string BaseUrl)
{
baseUrl = BaseUrl;
}
}
I would like to use BaseUrl from base controller into attribute as follows-
public class LoginController : BaseController
{
[CheckQueryString(BaseUrl)]
public ActionResult LoginSuccess()
{
return View();
}
}
Is there any way to do it?
You couldn't pass a variable or object reference in attribute constructor parameter because attributes will resolve at compile time so you can only pass constant by their constructor.
But if you exactly explain what you want to do may i can solve your problem in other way.

Can I use method hiding on an ActionResult that has the same signature as the base controller?

I have 2 controllers, one inheriting the other. I need to override an ActionResult from the base controller because I need to change to code to implement pagination in the plugin for nopCommerce. However, I get an AmbiguousMatchException because of the new ActionResult.
Base Controller:
public class BaseController : Controller {
public ActionResult Category(int categoryId, CatalogPagingFilteringModel command)
{
//original action result code
}
}
Customer Controller w/ inheritance
public class CustomController : BaseController {
public new ActionResult Category(int categoryId, CatalogPagingFilteringModel command)
{
// my pagination code with different model/view
}
}
Route Info:
Here I remove the route for the base controller and add a new route to use the CustomCatalog controller.
routes.Remove(routes["OriginalCategory"]);
routes.MapLocalizedRoute(
"OriginalCategory",
"Category/{categoryId}/{SeName}",
new { controller = "CustomCatalog", action = "Category", SeName = UrlParameter.Optional },
new { categoryId = #"\d+" },
new[] { "Nop.Plugin.Common.Web.Controllers" });
I then get an AmbiguousMatchException
[AmbiguousMatchException: The current request for action 'Category' on
controller type 'CustomCatalogController' is ambiguous between the
following action methods: System.Web.Mvc.ActionResult Category(Int32,
Nop.Web.Models.Catalog.CatalogPagingFilteringModel) on type
Nop.Plugin.Common.Web.Controllers.CustomCatalogController
System.Web.Mvc.ActionResult Category(Int32,
Nop.Web.Models.Catalog.CatalogPagingFilteringModel) on type
Nop.Web.Controllers.CatalogController]
EDIT
The base controller resides in the core of the application where as the CustomController is in the plugin meaning that I cannot modify the base controller's type.
How about using virtual in the base controller and override in the derived controller instead of new?
base:
public virtual ActionResult Category(...) { }
derived:
public override ActionResult Category(...) { }
You cannot override a method which has not been declared virtual.
You can either define a new method with a different signature or you can encapsulate the functionality of the original class by maintaining a private reference to it in a wrapper class. It helps if you have an interface that you can implement from the base library (because this allows you to substitute the wrapper class where the base class that implements the same interface would be used), but you can do it without the interface, too.
// Base class source code is not modifiable
class BaseClass {
public ActionResult Category(...) {}
public ActionResult Other() {}
}
// Wrapper class can modify the behavior
class Wrapper {
private BaseClass baseClass = new BaseClass(); // Instantiate appropriately
public ActionResult Category(...) {
// do some stuff
}
public ActionResult Other() {
return baseClass.Other();
}
}

asp.net mvc 3 - call nonaction from other controller

I have 2 controllers CustomerController and PrivatemessageController
Customers has a nonaction method
private readonly ICustomerService _customerService;
public Customer(....) << autofac Ioc
{
}
[NonAction]
protected CustomerNavigationModel GetCustomerNavigationModel(Customer customer)
{
var model = new CustomerNavigationModel();
.... _customerSerice...
return model;
}
I'd like to get GetCustomerNavigationModel value from CustomerController as I don't want to recreate the same method for PrivateMessageController, is that possible in ASP.NET MVC 3.0 ?
Two options come to mind here.
Make the method public static:
[NonAction]
public static CustomerNavigationModel GetCustomerNavigationModel(Customer customer)
{
var model = new CustomerNavigationModel();
.... _customerSerice...
return model;
}
Create a base controller and implement the method there. Have both your controllers derive from your base controller:
public abstract class MyBaseController : Controller
{
[NonAction]
protected CustomerNavigationModel GetCustomerNavigationModel(Customer customer)
{
var model = new CustomerNavigationModel();
.... _customerSerice...
return model;
}
}
public class CustomerController : MyBaseController
{
....
}
public class PrivatemessageController : MyBaseController
{
....
}
Refactor the method into a separate class and use that class from your controllers. You can also just make the method static, and call it from PrivatemessageController using:
CustomerController.GetCustomerNavigationModel(customer);

ASP.Net MVC, Ninject IOC

I'm using Ninject to do some dependancy injection. (Mainly for the DAL), my project consists of 3 aspects and are as follows,
Project.Lib (Everything database,
services and anythign else that is
logic)
Project.Admin (Administration)
Project.Web (Front end what the user
see's)
Now, each of my controllers within my projects inherit from a BaseController
public abstract class BaseController : Controller
{
protected BaseController(ISession session)
{
_Session = session;
}
public ISession _Session { get; private set; }
}
And then and example controller might be like so,
public class ImageController : BaseController
{
private MediaService _mediaService;
public ImageController(ISession session) : base(session)
{
_mediaService = new MediaService(session);
}
[HttpGet]
public ActionResult List()
{
var RetVal = _mediaService.GetAllImages();
return View(RetVal);
}
}
As you can see the "Session" is passed from the controller to the service layer. I'm curious as to if this is good practie? ANy negitives to what we are doing here?
I'd avoid referencing ISession through your controller. A better solution would be to use Ninject to inject your services into your controllers. In this instance you'll need to create an abstraction for your MediaService class e.g.:
public interface IMediaService
{
SomeCollection GetAllImages();
// ...
}
You'd then use Ninject to supply an implementation of the above interface to your controller:
public class ImageController : BaseController
{
private IMediaService _mediaService;
public ImageController(IMediaService mediaService)
{
_mediaService = mediaService
}
[HttpGet]
public ActionResult List()
{
var RetVal = _mediaService.GetAllImages();
return View(RetVal);
}
}

Resources