Can two different controllers access a single view in mvc? - c#

I have two different controllers and I want both of them to use a Common View.
Is that possible?
Thanks in advance!!!!

Yes.Mention the view full path in the View method.
public class UserController : Controller
{
public ActionResult ShowUser()
{
return View();
}
}
public class AccountController : Controller
{
public ActionResult ShowAccount()
{
return View("~/Views/User/ShowUser.cshtml");
}
}
If the name of your Views are same in both the controllers, You can keep the Common view under the Views/Shared directory and simply call the View method without any parameter. The View name should be same as the Action method name.
public class UserController : Controller
{
public ActionResult ShowUser()
{
return View();
}
}
public class AccountController : Controller
{
public ActionResult ShowUser()
{
return View();
}
}
Assuming you have a View called ShowUser.cshtml under Views/Shared folder.

Related

View error when invoking methods from base controller in MVC 5

I have the following controllers
public class StoreController : Controller
{
public ActionResult Index()
{
var model = new SomeViewModel();
return View(model);
}
}
and
public class SofiaStoreController : StoreController
{
public ActionResult GetIndex(string city)
{
return base.Index();
}
}
When invoking the base Index method from the derived class I get this error:
The view 'getindex' or its master was not found or no view engine
supports the searched locations. The following locations were
searched:
Seems the GetIndex() method looks for a view in the derived controller's view folder by default even though no View() method is called but since there isn't such the error occurs.
Any idea why the method implicitly looks for a view and how to overcome the error ?
EDIT: After spending some time research the problem I came across these two posts: http://howtoprogram.eu/question/asp-net-c-asp-net-mvc-inherited-controller-using-base-view,2445 and http://www.davidwhitney.co.uk/Blog/2010/01/19/asp-net-mvc-view-engine-that-supports-view-path-inheritance/ Seems that controller inheritance is not that popular or straightforward decision. The solutions to my problem could be :
1. Not to use controller inheritance
2. Creating a custom view engine as shown in the second link (advanced)
3. As other people mentioned bellow - using full path to the view or RedirectToAction also could work
It does look for a view based on the Action method name you originally called. You can always override this behavior if you use the overloaded View() method that accepts the view name/path:
public class StoreController : Controller
{
public ActionResult Index(string viewName = "Index")
{
var model = new SomeViewModel();
return View(viewName, model);
}
}
public class SofiaStoreController : StoreController
{
public ActionResult GetIndex(string city)
{
return base.Index();
}
}

MVC - dynamic role management

I have users that have one of those roles:
RoleA (Attribute: AuthorizeRoleA)
RoleB (Attribute: AuthorizeRoleB)
In my controller I want to say this:
Everyone that has role of type RoleA
can access all the methods in this controller
[AuthorizeRoleA]
public class HomeController : Controller
{
public ActionResult MethodOne()
{
return View();
}
public ActionResult MethodTwo()
{
return View();
}
//****** Make an exception ********
//So in this case, let RoleA here, but let RoleB too.
[AuthorizeRoleB]
public ActionResult MethodThree()
{
return View();
}
}
And I have another controller:
Everyone that has role of type RoleB
can access all the methods in this controller
Just RoleB! No one else.
[AuthorizeRoleB]
public class AnotherController : Controller
{
public ActionResult Index()
{
return View();
}
}
So, this should be similar with the Authorize attribute when is used to decorate the controller, and the AllowAnonymous when is used inside the same controller, but I don't know how to achieve this behavior with custom attributes(filters).
My goal is to create custom attributes, where I can say:
In AuthorizeRoleA will be included n-roles
and in AuthorizeRoleB will be included n-other roles.
But AuthorizeRoleA will have highest priority than the other attributes.
Note: Maybe this is a duplicate, but I didn't find anything similar to this question.

Where to put common code in view controller View functions?

In one of the controllers, every view has a fixed preprocessing. Is there a better way of doing this, instead of the below code; such that SomeFunctionAsync works without writing that line before return View() for all functions with return View() in this controller? I also have some ajax post functions.
public async Task<ActionResult> View1()
{
await SomeFunctionAsync();
return View();
}
public async Task<ActionResult> View2()
{
await SomeFunctionAsync();
return View();
}
In other words, at the end I want to be able to write the following with having the same effect
public async Task<ActionResult> View1()
{
return View();
}
public async Task<ActionResult> View2()
{
return View();
}
If Action Filter as suggested by Varun doesnt suits you, you can try another way.
Create a parent View of all the view. In the action method for your parent view. Call this Method SomeFunctionAsync(). Thus, parent view will be called for all of yours views and the required method will be executed
You can create a base class for your controller, and have have each view in your code call a generic method. I use GetView as a method name (or you could override the existing ones).
Like so:
public class MyControllerBase : Controller {
public Task<ActionResult> GetView() {
yourCommonMethod();
return View();
}
public Task<ActionResult> GetView(string viewName) {
yourCommonMethod();
return View(viewName);
}
public Task<ActionResult> GetView(object model) {
yourCommonMethod();
return View(model);
}
public Task<ActionResult> GetView(string viewName, object model) {
yourCommonMethod();
return View(viewName, model);
}
}
Then in your controller, inherit from that:
public class MyController : MyControllerBase {
public async Task<ActionResult> View1()
{
return GetView();
}
}
If the common method is the same for all controllers and has no controller-specific dependencies, it could be that simple. However, you may want to look at using generics as well:
public class MyControllerBase<T> : Controller {
// base class stuff here based on type T's interface
}
public class MyController : MyControllerBase<MyController> {
// regular class here, sending MyController to the base
}
These are pretty much building blocks of OOP. You may do well to get a book that covers the basics of OOP and work through this type of stuff.
There are tow ways :
Use a single Action with different views like return View("View1") or retrun View("View2"), you can make if else conditions there so you will call your function at a single place.
If you want to go with your current procedure(not recommended) then you have to use Action Filter attribute and decorate it on Controller level then every action would execute your logic before execution of your Action

Call another controller and use a different Layout for the called controller action MVC ASP.NET

Am new to MVC ASP.Net. I would like to call an action method from another controller and use a different layout page.
My Views/Shared folder has two layout pages: ~/Views/Shared/_Layout1.cshtml and ~/Views/Shared/_Layout2.cshtml. Below is my code:
//HomeController
public class HomeController : Controller
{
public ActionResult Index(string id)
{
if(String.IsNullOrEmpty(id))
{
//Call someMethod from UserController
//And when called, it should a different Layout page: ~/Views/Shared/_Layout2.cshtml
return View("someMethod");
}
else
{
return AboutPage(id); //uses ~/Views/Shared/_Layout1.cshtml
}
}
public ActionResult AboutPage(string id)
{
return View();
}
}
If you want to use different layout then you can use overloaded version of View method:
return View("view", "_Layout1");
If you want to redirect control flow to different controller/action then:
return RedirectToAction("action", "controller");

how to create 2 controllers with same actionresult 2 views but one implementation

I got a controller in my mvc application like below.
public class BaseController: Controller
{
protected void LogInfo()
{
logger.InfoFormat("[SessionID: {0}, RemoteIP: {1}]", Session.SessionID, Request.UserHostAddress); }
}
public class FirstController : BaseController
{
public ActionResult Index(string name)
{
LogInfo();
getQueryString();
if(IsValidRec())
{
if(Errors()))
{
return View("Error");
}
var viewname = getViewName(name);
return view(viewname);
}
else
return view("NotFound");
}
}
I need to create another controller(SecondController ) with same ActionResult method that FirstController has but without any implementation. Because I dont wont to repeat same code in 2 ActionResult methods.
what is the best way to do that. I tried in following way but I m getting error when I initialize my protected method 'LogInfo()'
public class SecondController : BaseController
{
public ActionResult Index(string name)
{
var firstcontroller = new FirstController();
return firstcontroller.Index(name);
}
}
Put the part you want to re-use in the base controller
e.g.
public class BaseController: Controller
{
protected void LogInfo()
{ ... }
virtual public ActionResult Index(string name)
{
LogInfo();
getQueryString();
.....
var viewname = getViewName(name);
return view(viewname);
}
}
public class FirstController : BaseController
{
override public ActionResult Index(string name)
{
var result = base.Index(name);
.... do more stuff ...
return result;
}
}
public class SecondController : BaseController
{
// Don't need to override index if you
// want to do the same as in the base controller
}
You can use inheritance like this (one way):
public abstract class MyControllerBase : Controller
{
// whatever parameters
protected SharedModel GetSharedModel()
{
// do logic
// return model
}
}
public class OneController : MyControllerBase
{
protected ActionResult Index()
{
var model = this.GetSharedModel()
return this.View(model);
}
}
public class TwoController : MyControllerBase
{
protected ActionResult Index()
{
var model = this.GetSharedModel()
return this.View(model);
}
}
It is better to put common functionality somewhere else in application and use that in both controller. Like we used to write helper classes or use shared services. It is not good to create the instance of controller and calling the Action method from that...from the Architectural point of view. If u still have doubt...please explain more about your common functionality...then I will be able to help more.
There are two solutions to this type of issue: inheritance and composition.
In general, inheritance has less code, but is less flexible.
Here's a more through discussion.

Categories