How to get a common element (like Version number) into Site.Master? - asp.net-mvc

Suppose I have a Site.Master page.
I want to display something like the version number of the application (lets assume it is available in the the BaseController as a string) in the Site.Master.
What would be the best way to do that? I know one way would be to have a Base view model class which would contain the version element. But any better way?
Hope the question is valid.
Thnx,
Karan

I would write a helper method for this:
public static class HtmlExtensions
{
public static MvcHtmlString Version(this HtmlHelper htmlHelper)
{
string version = FetchVersionFromSomewhere();
return MvcHtmlString.Create(version);
}
}
And then in your master:
<%: Html.Version() %>

For something like an assembly version number it might be Ok to have it as a static property on the BaseController, in which case you could reference it directly from any code that needed it.
<%# Import Namespace="ControllerNamespace"%>
<%=BaseController.MyProperty %>

Related

How do I create something similar to the HTMLHelper namespace for the business name?

I would like to create something that can be called into any view in a website like this
#MyBusinessName.TelephoneNumber
#MyBusinessName.Address
etc...
In the same way I would call a HtmlHelper
#Html.ActionLink()
How do I add a namespace like "MyBusinessName" for use in an MVC view?
Html in Razor pages is a property of the class that pages inherit from, so of course you can't implement what you want in the same way as the standard HTML helper works. But I can suggest a different solution.
You may define a static class in your project that will work as your own helper (define there static methods/properties you want to use in views). I'd suggest something like the following:
using System.Web.Mvc;
namespace YourProject.Infrastructure {
public static class YourBusinessHelper {
public static MvcHtmlString TextBox(string name) {
string html = string.Format("<input name=\"{0}\" />", name);
return new MvcHtmlString(html);
}
// ...
}
}
System.Web.Mvc.MvcHtmlString is a class representing HTML markup that an HTML helper method inserts into the view where it is used. You may create it using a constructor that receives a string parameter containing the needed HTML markup — like in my code.
Now you can use this class in your views. You just need to import the containing namespace with this Razor instruction:
#using YourProject.Infrastructure
I'd suggest to put it into the view start file (_ViewStart.cshtml) so that it applies to all your views.
The sample helper method above can be used simply:
#YourBusinessHelper.TextBox("TextBoxName")
UPDATE: you may also create an extension method for HtmlHelper:
using System.Web.Mvc;
namespace YourProject.Infrastructure {
public static class YourBusinessHelper {
public static string CompanyPhoneNumber(this HtmlHelper helper) {
return "+82649256720";
}
// ...
}
}
You may use string not MvcHtmlString in helper methods if they return plain text (no HTML markup).
Use it like a built-in helper method:
#:Call us: #Html.CompanyPhoneNumber()

Is it possible to make HtmlHelper extension method available to only those views with specific type

I'm trying to implement my own paging for IEnumerable collections. So, I have a class called PagedList. I'm done with the class itself, I just need to write an HtmlHelper extension method that will render the actual pages. This would be the simplest way to go (at least I can think of):
public static MvcHtmlString Paginate<TModel>(this HtmlHelper<TModel>,string url){
//do the stuff here
return new MvcHtmlString("Hi");
}
But, is it possible to make this method available ONLY in those views that are strongly typed to PagedList?
While #Ehsan Sajjad's answer is correct, I've found a neater way to accomplish this:
public static MvcHtmlString Paginate<T>(this HtmlHelper<PagedList<T>> helper,string url){
.......
}
I've tried and it really works. But there might be some other implications that I cannot think of at the moment, so any comments or corrections are welcome.
You can put constraint on method so that it can only be called on specific types, for Example IEnumerable<PagedList>, PagedList<TModel> or PagedList if you want, it depends on what Type of model you want, and also depends on implementation of your PagedList class:
public static MvcHtmlString Paginate<TModel>(this HtmlHelper<TModel> helper,string url) where TModel : IEnmerable<PagedList> {
//do the stuff here
return new MvcHtmlString("Hi");
}

Dynamically replacing content in views

I have a situation where our core project requires heavy templating.
We have come up with a solution which should make the project very flexible, but I am unsure how to implement a solution.
In our views I want to be able to place custom tags like this:
<div class="some view">
{{SomeTag}}
</div>
Now these tags don't have anything to do with the model, what we want to do is to replace these tags at runtime on the server (not the browser!) with the contents of a file on the server (under some designated directory) called "SomeTag.html".
Is there some way to add a method or override a method in a Base Controller (which will inherit "Controller") which searches through the output of the view for any {{Tag}} and does a replace with it's corresponding Tag.html file?
For example perhaps this is appropriate?
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
}
You could use a modified form of
HtmlHelper.Partial(partialViewName)
You can write an extension method specific to your scenario
public static MvcHtmlString Template(this HtmlHelper htmlHelper, string templateKey)
{
string partialViewName = null;
// get partialViewName according to the template key
return htmlHelper.Partial(partialViewName);
}
You will use it like
#Html.Template("SomeTag")

create a textarea helper that takes content of the view as a parameter

I would like to create a html helper that would receive as a parameter content of the view, like this:
<% Html.MyTextArea("txt1", () => {%>
content of the view
<%=Html.TextBox("Name") %>
...
<% }) %>
Since you've tagged it as MVC, I'm going to propose you could do something like I posted on my blog as a way to get syntax highlighting for templates as the solution would be very similar, IF you don't need to manipulate the inner content and are simply interested in 'wrapping' it in some way (like in a containing element that requires some extra logic).
Using the technique, the HtmlHelper method receives the context of the block. The syntax is slightly different from your suggested technique though.
For example, you could have something like:
#using(Html.MyTextArea("txt1"))
{
<some HTML content here>
}
The context is passed to an IDisposable object which includes a Writer (for writing to the current output stream). There, it can output multiple elements or do other manipulation as needed. The Dispose is used to write a close element (if needed).
So, you could end up with something like this:
<textarea><some HTML content here></textarea>
However, as I mentioned this does not provide the inner content to the function itself.
As Razor pages render inside out, there's not an effective method to grab the output in the way you're wanting. There are some posts around about caching the output of a Partial to a string (which would mean the inner content in your example would be in another file, an .ascx file), so you might want to look at those.
One approach is,
public static MvcHtmlString TextArea(this HtmlHelper htmlHelper, string name, Action<TextWriter> action)
{
var writer = new StringWriter();
action(writer);
// here writer contains the html
return htmlHelper.TextArea(name);
}
<%:Html.TextArea("txt1",(writer) => {
writer.Write("content of the view");
writer.Write(HttpUtility.HtmlEncode(Html.TextBox("Name")));
}) %>
Do you mean something like this?
namespace System.Web.Mvc {
public static class HtmlHelperExtensions {
public static MvcHtmlString MyTextArea(this HtmlHelper htmlHelper, string id, Func<MvcHtmlString> helperFunc) {
return new MvcHtmlString(string.Format("<div id=\"{0}\">{1}</div>", id, helperFunc()));
}
}
}
You can use this way:
<%: Html.MyTextArea("txt1", () => Html.TextBox("Name", "abc")) %>

ASP MVC Razor view extension methods, how to create 'global' view methods?

I am using Razor view with asp mvc preview 3
I am trying to create some methods which I would like available directly in the views. These are not really Html helper methods so I don't think extending HtmlHelper makes sense?
my goal, be able to call methods in the view i.e.
#HelloWorld(); vs #Html.HelloWorld()
I can get Html.HelloWorld to work by creating an extension method on HtmlHelper
public static class HtmlExtensions
{
public static string HelloWorld(this HtmlHelper helper)
{
return "Hello";
}
}
I would like to do the same thing but for the view; my problem - what type of object is the view?
Note: I was able to get this to work by defining the methods in the .cshtml page
#functions
{
public string HelloWorld()
{
return "Hello";
}
}
#HelloWorld() #* now this works *#
then I tried to put this code my _viewstart.cshtml file thinking it would be available in all views but it was not
if I knew which type the view was I think it could be easily extended, any help appreciated
As remarked by others, Razor Views all ultimately inherit from WebViewPage:
public abstract class WebViewPage<TModel> : WebViewPage
You can therefore simply write your extension methods for WebViewPage without creating a new base class or changing the config files, which has been suggested by other answers. For example:
public static class WebViewPageExtensions
{
public static string HollowWorld(this WebViewPage wvp)
{
return "Memento mori";
}
}
Add a using statement for that namespace to your View and then:
<p>#this.HollowWorld()</p>
it turns out, the asp runtime is going to define the Execute method at runtime, so the custom view base class must also be abstract
using System;
using System.Web.Mvc;
namespace MyMvcWebApp.Extensions
{
public abstract class ViewBase<TModel>
: System.Web.Mvc.WebViewPage<TModel> where TModel : class
{
// now this will be available in any view #HelloWorld()
public string HelloWorld()
{
return "Hello from the ViewBase class";
}
}
}
this should work with strongly typed views, it looks like with razor all views are strongly typed, when you do not define the type 'dynamic' is used and that is the strong type
also, as Clicktricity stated you then update the web.config (the one under the Views directory)
<pages pageBaseType="MyMvcWebApp.Extensions.ViewBase">
The default base class for Razor views is specified in the Web.config located in the views directory. Usually it is:
<pages pageBaseType="System.Web.Mvc.WebViewPage">
I've not tried it, but I would suggest inheriting from this base class and adding your own functionality, then adjust the web.config accordingly.
The best way to call a method with arguments using razor engine is to use helpers.
Example: let you have a helper #MakeNote(string content)
Then in cshtml page you just need to call #MakeNote("Hi") and you should be fine.
I was going crazy when I was having problem then google sent me to this page but it did not help. I was trying to load content in html <select> with L2E using razor.
The secret is to create a helper in app_code then use with cshtml.

Resources