ViewBag and Models are not avaialable when tried Pluggable MVC areas - asp.net-mvc-3

I have tried the pluggable structure as discussed in this post:
Pluggable MVC view return null
It is also explained in this post: http://www.wynia.org/wordpress/2008/12/aspnet-mvc-plugins/
When I try to access ViewBag/Model in one of the area, it gives me this error:
The name 'ViewBag' does not exist in the current context
The name 'model' does not exist in the current context***

Since you are serving the view from an unknown location there's no longer the ~/Views/web.config that applies to it. And as you know inside this file is specified the base type for Razor views (System.Web.Mvc.WebViewPage). So one possibility is to add an #inherits directive to the top of your view:
#inherits System.Web.Mvc.WebViewPage
#model MyViewModel
<div>#ViewBag.FooBar</div>
Side-note: since you already have a view model why even care about ViewBag? Why not get rid of it?

Related

ASP.NET Core populate model only once for all views

I'm new with ASP.Net Core (3.0 in this case) and I´m trying to create a menu that is visible on all views of a WebApplication, is created dynamically and must be populated only once. Below i explain the steps and try outs i did to reach the goal needed (if required i can share the code I'm using).
This is what i did:
In a simple way, using the "_Layout.cshtml" page, i created a static HTML menu and made all other views simply inherit that layout. So far, so good;
Next challenge comes from the fact that the menu items are dynamically created after a User has logged-in, which i managed to overcome by setting a ModelView inside a controller (HomeController.cs with Index action in this case), and then delivering it to the view. For this case works OK, because the default page is ~\Home\Index\, problem is when i change to a different view with a different controller, the menu has to be rendered again, and so i have to replicate the code (a problem dealt create a BaseController and BaseModel based on this post along side the OnActionExecuted to host the menu generating code)
Now, the biggest problem is the fact that i can only populate the menu once, after the user logs-in. Each time there is a redirect between different controllers/views (post-back of same controller/view works fine), the model is null inside the OnActionExecuted, I tried using ViewData, ViewBag, TemData, but all are null.
So, my question is, how to keep that specific data alive and shared, basically across all the views, and only gets populated once (after each user login) between redirects from different views?
I have been reading around and found several solutions besides the one i did, but i did not found any that could keep data alive throughout the user session the way I need:
ViewBag, ViewData and TempData
Can the shared layout view have a controller in ASP.NET MVC?
Pass data to layout that are common to all pages
To sum up, my flow at this moment, is like this:
User Logged-in
Redirect to default: ~\Home\Index
MenuModelView.cs for the menu gets built and HomeController.cs returns to Index.cshtml with the model attached to it.
Index.cshtml receives the populated ModelView and it uses _Layout.cshtml
The _Layout.cshtml builds the HTML tags for the menu based on the MenuModelView.cs data
User navigates to a different view and steps 3 to 5 are repeated from a specific controller/view
If you want to create a control that can be accessible in all pages without changing every controller, I strongly suggest creating a view component. For a view component has no relationship with your controller, but can access dependencies like database and full HTTP context.
For example, you want to build a custom nav menu, you can just create a view component named NavHeader
using Microsoft.AspNetCore.Mvc;
namespace YourProject.Views.Shared.Components.NavHeader
{
public class NavHeader : ViewComponent
{
public NavHeader(YourDbContext context)
{
// you can access your dependencies, like database.
}
public IViewComponentResult Invoke()
{
// your own logic. You can access HTTPContext here.
var model = new YourOwnModel();
return View(model);
}
}
}
And just call it in any view or layout.
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
</head>
<body>
#*Render your component like this*#
<vc:nav-header></vc:nav-header>
</body>
For more details about view component, please reference:
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-3.1
https://anduin.aiursoft.com/post/2020/1/4/share-view-component-between-different-aspnet-core-web-project

Dynamic viewmodels /Viewmodels at external location in MVC3

I have a page which consists of multiple partial views uploaded by a user. I have customized the Razor viewEngine to look at different locations for the .cshtml files.
Now if i'm rendering a partial view _abc.cshtml(found on my external location) and this partial view requires a viewmodel AbcViewModel, whats the best way to deal with this?
option 1: I have a DB entry that specifies _abc.cshtml uses AbcViewModel. So once I find the partial view, i'll know which viewmodel to use..In this case the ViewModel resides in the solution itself.
Using reflection I can get the class
Assembly assembly = Assembly.GetExecutingAssembly();
AbcViewModel viewModel= assembly.CreateInstance("AbcViewModel") as AbcViewModel;
I was wondering if there is a way that I could have the viewModel at an external location..this way I can extend my application..

i got error the name 'model' does not exist in current content

I can use #model in cshtml in views folder bu i want to use this another folder for login operation.
I create a cshtml file in Account folder.But i cant use #model.I got error like this:
You need to provide the class that will be used as the model for this view, ie.
#model MyApp.Web.Models.ViewModels.AccountModel
If you don't need a strongly-typed model in this view just delete #model declaration.
http://weblogs.asp.net/scottgu/archive/2010/10/19/asp-net-mvc-3-new-model-directive-support-in-razor.aspx

MVC3 Finding a control by its Name

I have a C#.Net web app and I am trying to access one of the HTML/ASP Text Boxes in the Controller for the Edit View of my Proposal model. In a non-MVC app, I was able to do this using Control.ControlCollection.Find(). Is there an equivalent for a MVC3 project?
You ask for an equivalent of Control.ControlCollection.Find() in MVC?
In MVC your controller is not aware of controls.
The controller just receives data via parameters and returns data via the function result.
What do you want to do with the control in your controller code?
If you want to access the value, you should bind it to a parameter:
View:
<input name="MyControl" type="text" />
Controller:
public ActionResult MyAction(string MyControl) {
// MyControl contains the value of the input with name MyControl
}
The MVC pattern was designed to keep things separated.
The View has no knowledge of the controller at all
The Controller only knows that a view exists and what kind of data that it needs. It do not know how the data is render.
Hence, you can never get information about controls/tags in the view from the controller. You need to use javascript/jQuery in the view and invoke the proper action in the controller.
In an MVC-application you don't have controls like in a webform-application.
In MVC you collect your required data in the controller and pass it to the view.
Typicaly the view is a HTML-page with embedded code.
In opposite to controls in webforms which produce HTML and handles the post-backs in MVC you have to do all this manually. So you don't have controls with properties and events wich you can access easily in the controller and you have to handle all your posts with your own code.
Thats sounds as it is a lot of more work - and indeed it could be if you implement the behaviour of complex controls - but MVC applications are much better to maintain and you have 100% influence to the produced HTML.
Well probably i am late for this but it should help others in future...u can store ur value in hidden field in view and then access that value in controller by following code..
Request.Form["hfAnswerOrder"].ToString();
Point - hfAnswerOrder is the ID of the hidden field
My Control in cshtml page..
#Html.Hidden("hfAnswerOrder", Model.Answers.ToList()[0].AnswerOrder)

How does ASP.NET MVC arbitrate between two identically named views (aspx and razor)?

Using ASP.NET MVC3 I created a new Razor view and gave it the same name as the existing .aspx view that I had been using. I noticed that controller continued to pick up the .aspx view (which has the same name as the action) which is pretty much what I expected. I then renamed the .aspx view and action picked up the razor .cshtml view.
So if I have two views called myview.aspx and myview.cshtml and an Action called MyView() that does a return View(), it will pick up the myview.aspx view and return that.
How does MVC3 decided which view-type to default to?
Is there a way to change this default behavior to prefer a razor view over an .aspx view?
Everything stems down to the order of view engines in the ViewEngines.Engines collection. Here's how the ViewEngines static constructor looks like (as seen with Reflector in ASP.NET MVC 3 RTM):
static ViewEngines()
{
ViewEngineCollection engines = new ViewEngineCollection();
engines.Add(new WebFormViewEngine());
engines.Add(new RazorViewEngine());
_engines = engines;
}
which explains why WebForms is the preferred view engine.
So you could perform the following grotesque hack in Application_Start to inverse the preference towards Razor :-)
var aspxVe = ViewEngines.Engines[0];
var razorVe = ViewEngines.Engines[1];
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(razorVe);
ViewEngines.Engines.Add(aspxVe);
I would imagine its down to the order in which view engines are registered. Earlier registered view engines will be queried first. If you want to change the order:
ViewEngines.Engines.Insert(0, ...);

Resources