custom base page for razor helpers - c#

I have a project where I have several custom properties and static methods available to the base WebPage class of a Razor view... ie, I have...
<system.web.webPages.razor>
<pages pageBaseType="myNamespace.WebView">
</pages>
</system.web.webPages.razor>
in my web.config. this is great. However, in my helper files, it is using the existing base class...
In this case, if I want to get access to some of those methods/properties/etc... I have to call the CurrentPage object, cast it to my custom baseclass object, then get the methods I want. In order to make the markup in the helpers simpler and cleaner, I would like to just define some static properties to grab the relevant data...
I have accomplished this nicely with some static methods and properties inside of a #functions{} block, but I would like to override the base class that exposes the CurrentPage property instead, so that I have it available by default in all of my helper files, and I won't have to repeat code...
It looks like the HelperPage implements the WebPageRenderingBase...
looking at the MSDN doc for the RazorPagesSection configuration, it doesn't look like there is anywhere else to modify it...
is there a similar configSection that I can define to override the HelperPage base type??? this would be super helpful. thanks.

Related

Caliburn.Micro : locating Views when inheriting Viewmodels

I'm trying to connect multiple Viewmodels to a single View using caliburn micro. I found some solution but all seem quite heavy for something that seems to me a quite standard way of doing things.
The reason for being that is the following :
I'm implementing some views and their default ViewModels in an assembly. lets call the assembly HMI.Base with two classes
HMI.Base.ViewModels.BaseViewModel
HMI.Base.Views.BaseViewModel.
I'm then using this view from another assembly. lets call the assembly HMI.ConcreteApp
Usage is quite straightforward and overriding SelectAssemblies() does the trick so the view can be easily located.
Issues are rising when a ViewModel needs to get its data from a specific source. The solution that come to my mind is to extend my ViewModel and Add an element in its constructor being the source of my data and then do the necessary to link those data to the base viewmodel Properties.
So I create a class
HMI.Concrete.ViewModels.CustomViewModel
The implementation looks like this:
using HMI.Base.ViewModels;
public class CustomViewModel : BaseViewModel
{
public CustomViewModel (IConfiguration config, ILoggerFactory loggerFactory, IEventAggregator eventAggregator, DataSourceXYZ data) : base(config, loggerFactory, eventAggregator)
{
Logger.LogInformation("Constructing custom viewmodel that will display as HMI.Base.Views.BaseViewModel");
}
However the name has now changed, so the view cannot be located automatically. Is there a way to simply and clearly say "Use the base class view if no specific view exist with the same name" in the CustomViewModel ?
Without having to do some more fiddling in the bootstrapper, which seems bad to me (except if it isn't ) because all needed extra information are there (we know the base viewmodel why not use the base view to display the data)
I will provide already an answer for the best solution I found even if I would like better:
The solution is at this page
In short :
A custom attribute can be created to indicate the baseViewModel.
The Viewlocator can be changed in the Bootstraper to take it into consideration
And an extra step not in this article to avoid writing it in every application:
create A CustomBaseBoostrapper to write it only once and use it instead of BootstrapperBase.
It is not too bad, but I'm mainly wondering if there is not better and without changing the viewlocator.

Sitecore - how can I work with the 'sublayout parameter helper'?

i'm new in the sitecore/C# story and need some help with a helper.
I downloaded the sublayout parameter helper from "http://marketplace.sitecore.net/en/Modules/Sub_Layout_Parameter_Helper.aspx"
This gets me 2 .cs files with their own namespace: Sitecore.Sharedsource.Web.UI.Sublayouts
How can I implement these in my own solution so that I can use them?
Thanks in advance!
You need to make your Sublayout codebehinds inherit from the SublayoutBase (which inherits from UserControl). In that way you can use the properties in that class. For instance you can access DataSourceItem etc.
So you should include the files in your project and then in your sublayouts have something like this:
public partial class LatestNewsSpot : SublayoutBase
And then you can do stuff like:
Item datasourceItem = DataSourceItem;

How to access (custom) web helpers from within ViewStart?

I have defined some custom helpers in my MVC3 Razor application (ASP.NET) and in the ViewStart code I would like to access my custom helpers.
I noticed that they are not accessible in _ViewStart which then seems understandable as ViewStart derives from ViewStartPage and not WebViewPage.
So I tried to define the helper in a custom ViewStart class but as it turns out I then need access to a ViewDataContainer to be able to initialize the helper.
So, the question is, how can I access my custom helper from ViewStart (or a custom ViewStartPage) and if not, can I then initialize the viewDataContainer constructor property with NULL. I don't expect needing any ViewData access in my custom ViewStartPage.
I also tried implementing the custom ViewStart class but it gives me this error:
CustomViewStart does not implement inherited abstract member 'System.Web.WebPages.WebPageExecutingBase.Execute()'
what should I do in that execute method? I don't want to do anything fancy in the customViewStart, just access my helper.
OK, it is after all possible as I suspected, just needed some nitty gritty technical details sorted out first.
public abstract class CustomViewStartPage : System.Web.Mvc.ViewStartPage {
public Helpers.InvariantHelper ConfigHelper { get; private set; }
public CustomViewStartPage() : base() {
ConfigHelper = new Helpers.InvariantHelper();
}
}
Now, I have defined several custom helpers in my WebViewPage custom base page and they do their work for views. However, in the ViewStart I needed to do certain stuff (here is only a trivial example) that did not require accessing the ViewContext (as I originally thought).
So, with this I can now have this in my _ViewStart.cshtml:
#* Views/_ViewStart.cshtml *#
#inherits MyNamespace.Web.Mvc.CustomViewStartPage
#{
var something = ConfigHelper.DisableParentLayout;
}
Sure, one can also use static members of a class as #MortenMertner indicated (a fresh view at the problem from outside) but in some cases that may not be what you truly want. This example here is senseless but serves as purpose to indicate how it could be accomplished for those who need.
If on the other hand a ViewContext needs to be accessed (another valid scenario) you may want to look at the post in my comment above which describes how to modify this custom view start page to access the context without errors.
From what I understand, the _ViewStart file is not a regular view. It can only be used to set defaults, such as the layout view, for other views.
For instance, this is the complete contents of my _ViewStart file:
#{ Layout = "~/Views/Shared/Layouts/Wide.cshtml"; }
If this holds true there would be no need for custom helpers in the file, and you're likely trying to solve a problem that you shouldn't have in the first place.
As an aside, you can add assemblies and namespaces in Web.config to avoid having to import them in specific views. I use this to import my models, enums and extension methods.

Using dynamic class/properties at runtime to load configuration

I'm having a conundrum here, and I'm not even sure it's possible.
I'm developing a pluginbased application, where all the plugins will have access (read/write) to a shared configuration on the host application. There are easier ways of achieving the problem I'm presenting, but since this is a non-work related project, I'm free to play around :)
Let's say we have Plugin_A that is inheriting a PluginBase abstract class. The abstract class exposes a IConfiguration Config property that can be accessed by the plugin to write to this shared configuration. The IConfiguration Config is set properly by the host upon loading the plugin, to limit the available configuration that particular plugin will access.
What I would like to do is try and use the Dynamic keyword in C# 4.0 to seamlessly write the config-class.
in pseudo C# code here's what I would like to achieve
public class Plugin_A: PluginBase
{
public void DoSomethingWithConfig()
{
ShowAMessageBox(Config.SomeMessage);
Config.HasShownMessage = true;
}
}
Now - in this example I don't want to actually define the .SomeMessage and .HasShownMessage but rather have them be dynamic and returned when called upon.
It seems like a stretch, but is this at all possible?
I don't think you want to implement the IDynamicObject interface, I recommend you have Config inherit from DynamicObject instead. You'll want to override TryGetMember and TrySetMember at least for your example. TryInvokeMember will be necessary if you want to dynamically call methods. Implementing the whole interface is much more difficult.
So, your config class(es) will need to inherit DynamicObject and implement IConfiguration. You can then either declare the field as a dynamic item or as IConfiguration objects and cast them dynamic before you want to use their dynamic behaviors.

How to give a custom ASP.NET control the ability to parse XML markup to a collection?

I'm writing a custom ASP.NET webcontrol and would like it to have a collection of custom items which can also be specified in the XML markup. Something like this:
class MyControl: WebControl
{
public IList<MyItemType> MyItems { get; private set; }
}
And in the markup:
<asd:MyControl runat="server" id="mc1">
<MyItems>
<MyDerivedCustomItem asd="dsa"/>
<MyOtherDerivedCustomItem asd="dsa"/>
</MyItems>
</asd:MyControl>
How do I do this? I though this was all about implementing some interface on the collection or adding some special attributes to the property, but nothing I do seems to work.
Ha, got it!
Seems that IList<T> is a bad type to return. It needs to be something that implements plain old IList. Though the implementation can be explicit. Providing method overrides with the same names but strongly typed arguments will limit the available options in the markup editor.
Well, of course, adding the standard attributes also seems to be necessary:
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[MergableProperty(false)]
Not sure what they all do (the documentation is pretty nondescriptive in many places), but it works!
Perhaps this MSDN article will give you a head start: http://msdn.microsoft.com/en-us/library/9txe1d4x.aspx
One of the important attributes to look at is:
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
which will give the desired effect...
HTH.

Categories