What's the base class of a Razor View in ASP.NET MVC3 - asp.net

I'm trying to have all my views inherit from a custom class so that I can add certain behaviour and values to all pages, but I'm having some issues. I tried subclassing System.Web.Mvc.WebViewPage but I'm forced to implement an Execute procedure that I don't know what it should do. Also, if I try to access the Context variable, I get a null reference (really weird). This leads me to think that I may have the wrong base class....
Any thoughts?

Diego, System.Web.Mvc.WebViewPage is the right base type (and you should have another class inheriting from System.Web.Mvc.WebViewPage<TModel> if you want strongly-typed views). You should mark your own class as abstract so that you are not forced to implement the Execute method.
Update: To configure all your views to use your custom base class, look into the ~\Views\Web.config file. Inside of it there's a Razor-specific section where you can use the pageBaseType attribute to configure your custom type.
As far as the Context property is concerned, it should be fully initialized once the view is executing. However, it might not be available if you try to access it too early (for example, from your classes constructor). When are you trying to access it?
The Execute method is something that is provided by the Razor compiler when your view is compiled. For example, given the following view file
Hello #Name!
The Razor compiler will behind the scenes generate the following class (this is a simplification, so the details might be off, but it should convey the point)
public class _Some_Generated_Class_Name_ : System.Web.Mvc.WebViewPage {
public void Execute() {
Write("Hello ");
Write(Name);
Write("!");
}
}
Then the framework calls the Execute method on your view class and your view gets executed.

Related

How to pass an object from one page component to another page component in a .NET Blazor app?

I have a .NET Blazor Server app and need to pass an object from one component to another. Both components are pages, meaning that they have #page directives with routes. I know how to use cascading values to pass a parameter between regular Blazor components, but this does not work with page components. I also know how to pass a parameter within an endpoint route. However, instead of a string or int I want to pass an object with multiple properties and am unsure how to best accomplish this.
Is it possible to pass an object as an endpoint route parameter? If not, what is a good way to accomplish this within a Razor components context?
Using dependency injection would likely solve this issue for you.
Example:
Create a class called "ApplicationService"
Create an interface in that class called "IApplicationService"
You could have something like this
public interface IApplicationService
{
public Task MsgBox(string value);
}
In the ApplicationService class inside the "ApplicationService.cs" file, go ahead and implement the interface member above.
You could have something like this:
public async Task MsgBox(string value)
{
await _JSRuntime.InvokeAsync<string>("alert", value);
}
In the program.cs class, you need to now register that "service" we just created.
You could have something like this
builder.Services.AddTransient<IApplicationService, ApplicationService>();
builder.Services.AddScoped<ApplicationService>();
In your _Imports.razor you can inject the class so that the pages have access to it:
#inject ApplicationService MainAppService;
Now in your razor components you should be able to do something like this:
await MainAppService.MsgBox("This is a message box");
This works in my WASM blazor app, hope it sheds some light on the server side of things 🚀
Use a DI service. Create a class to hold your object. Add it as a Scoped Service in Program. Use it in any component (pages are just components with a page attribute) though #inject.

Storing a view in Xamarin.Forms MvvmCross

I have an app with four main pages, switched through a tab bar (no "back" button).
One page has a lot of content (ScrollView) and takes quite a few seconds until it's rendered. I handle that by showing a "loading" overlay while the work is done. But for that specific page I'd like to keep the view alive, so that when the user switches to another page and comes back later, the page is ready without loading everything again.
I'm not sure how to do that in MvvmCross, though.
I did read the documentation and from what I understood the View Presenter would be the right way to do it, since the docs say:
"Another kind of presentation changes your app can request through
hints includes clearing / modifying the BackStack, changing a root
while maintaining the existent views, … possibilities are really
endless. Once again your app is king here!"
I guess I would need to create a custom MvxPresentationHint for that, but I don't quite get it :(
How or rather where would I access and store/load the View?
I'm generally still quite unfamiliar with MvvmCross (how it works under the hood) and especially customization of Mvx classes, even though I've been using it for a while.
Any explanation and preferably code examples beyond what's written in the documentation would be extremely appreciated!
It isn't meaningful to attempt to "store" a view in MVVM. The XF view is a representation of what will be created with native (e.g. "Android" or "iOS") widgets. Creating and measuring/laying out those native widgets is what is slow. MVVM View Presenter won't speed up that logic.
Instead of "store", you need "keep alive":
For a ContentPage called MyPage, when you create it, store it in a static variable. Then re-use that variable. If you never need more than one of these, you can store it in the class itself.
Modify the "code behind", MyPage.xaml.cs:
public partial class MyPage : ContentPage
{
// Singleton Pattern.
private static MyPage _it;
public static MyPage It {
get {
if (_it == null)
_it = new MyPage();
return _it;
}
}
// "private", because calling this directly defeats the purpose. Instead, use `MyPage.It`.
private MyPage()
{
InitializeComponent();
}
}
To create it, whereever you would put:
new MyPage()
instead put this:
MyPage.It
For instance, you might do PushAsync(MyPage.It);
This will always return the SAME INSTANCE of MyPage. So once it has been created, it keeps its state.
IMPORTANT: Note that the constructor is only called ONCE. Any code that needs to be done each time the page appears, put in override .. OnAppearing() method.
LIMITATION: Views "expect" to be part of the visual hierarchy when they are manipulated. If you attempt to alter the page or its view model while it is not on the screen, you may encounter problems. Those are beyond the scope of this answer - create a new StackOverflow question with the details of any problem you encounter.

Looking for a way to implement a polymorphic view in ASP.NET Core

I'm working on an ASP.NET MVC Core web app that would have a lot of similar views. Each view is just a simple form that has a list of label&control pairs.
An "Object" editor template has been built in order to generate the content of such views automatically based on view model properties.
Each view would basically have just one line of code:
#Html.EditorFor(m => m)
Each view model is derived from a base class.
Is there a way to get rid of duplicate views and controller actions?
Ideally, I'd like to have just one view where the model is the base model class and one controller action that would receive that base model.
Himanshu's comment steered me to use Partials for the child classes and use the base class as the model for the main views. You may be able to just use reflection/property annotation to populate the views according to the given Model, though I have not tried it.
What I have tried successfully is using a base class that is not abstract and thus will not duplicate properties in the child classes, then using generics like...
List<T> GetChildClasses<T>() where T : BaseClass;
which is called by the controller method and supplies the View Model, and then displaying like this...
#model MyApp.Models.BaseClass
<div class="show_base_class_properties_here">
</div>
#if(Model is ChildClass)
{
#await Html.PartialAsync("_ChildPartial", Model);
}
<div class="whatever_comes_next">
</div>
I suspect there is a better way but this works. Apparently there can only be one #model in a view file.

Difficulty copying/extending singleton manager class

I want to extend or copy the PopUpManager class to add the ability to keep track of the number of windows.
I just want to add a simple windowCount++ when a window is added and windoCount-- when it's removed.
the problem is PopUpManager is a Singleton class... I wasn't able to make it work properly by extending it. And now I have tried to copy the code from the PopUpManager.as file and just add my variable to the end of its functions. It doesn't seem to be working though since it says my properties are undefined even though they are declared above the constructor.
I am thinking I would have to make a copy of the PopUpManagerImpl.as since that's wehre it seems much of the business resides (PopUpManagerImpl extends EventDispatcher implements IPopUpManager) would that allow me to have access to the variable? and should I ignore the manager and just put it in the implementation class?
here is a link about Using the Flex Singleton register, which helped me out when finding myself in the same situation.
I hope you can inspire from that too.
You likely didn't declare yours properties as static. The PopUpManager uses all static methods - this is why working with it you use syntax like:
PopUpManager.createPopUp(...
instead of
var popUpManager:PopUpManager = new PopUpManager();
popUpManager.createPopUp(...
This means that any variables declared in the PopUpManager need to also be static so as to be accessible at the class level.
public static var windowCount:int

call flex initComplete at a specific time

Below is the overriden on complete function for a preloader in Flex.
private function initComplete(e:Event):void
{
//dispatchEvent(new Event(Event.COMPLETE));
cp.status.text="Configuring... Please Wait";
}
What I want to do is when the app has finsihed loading I want to change the preloaders text to "configuring".
Then I want to go and do a bunch of setup stuff in my code.
Once I've done all the setup I wanted how can I get the Preloader to dispatch its Event.complete from else where in my code?
I tried Application.application.preloader but it comes up null.
So I guess my question really is how to access a preloader from anywhere in my application.
Would a better approach be to have all setup classes as members of my preloader class?
One thing that might help is a Model-View-Controller pattern. Are you using a framework for your application like Mate, Swiz, or Cairngorm?
If you were using Mate, for example, you could do something like this:
Create an AppStateManager class with a property (e.g. applicationState)
Create an EventMap with an EventHandler for the FlexEvent.INITIALIZE event. In this handler, set the AppStateManager.applicationState to something like "CONFIGURING"
Your EventMap has an injector that injects the applicationState property into a view. The injector listens for changes to this property and updates the view. In this case it might just be injected into your main view.
In the main view, you have a public bindable property also called applicationState that gets injected by Mate.
In the setter for this property, you can have an if/then or a switch that does different tasks depending on the state. For example, if applicationState == "COMPLETE", then this.preloader.dispatchEvent(Event.COMPLETE) or something like that.
The details are pseudo-sketched out but the idea is to use Flex's bindings to notify view components when changes have been made, and to have shared objects that maintain state. Not sure if that's what you're looking for...
The component LifeCycle does specific stuff in a specific order, and the near final element is to make the component visible.
It sounds to me like you want to defer this setting of visible to true to do other stuff. But, I imaging if you were making use of the component LifeCycle this would be a non-issue.
What sort of app init stuff do you need to do?

Resources