How to access User Identity detail in mvc HtmlExtension method? - asp.net-mvc

hellow guys thanks for your reply in advance.
I have to display many action links in many pages and I have authorization between user Roles so i am were coding if else in views but i wanna make it short thats why i go for htmlHelper extension method here is my code.
public static MvcHtmlString ValidationActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string AllowedRole)
{
if (User.IsInRole(AllowedRole))// its given me error The User dosent exist in current context Am i missing some namespace or what ?
{
htmlHelper.ActionLink(linkText, actionName);
}
}

You can access User within the extension method using
public static MvcHtmlString ValidationActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string AllowedRole)
{
var user = htmlHelper.ViewContext.HttpContext.User;
alternatively, you could pass User to the method by adding an additional parameter to your extension method.

Related

html.beginform in .NET - the third parameter seems to be take-it-or-leave-it

(Html.BeginForm("Search", "YOUR CONTROLLER", null)
I have the above code, and it links to a Controller method annotated as a Post, yet I don't have to put
(Html.BeginForm("Search", "YOUR CONTROLLER", FormMethod.Post)
Curious why this is, haven't quite fully wrapped by head around all the nuances of Html.BeginForm yet...
Html.BeginForm processes the method parameter using the method GetFormMethodString shown below:
public static string GetFormMethodString(FormMethod method)
{
switch (method)
{
case FormMethod.Get:
return "get";
case FormMethod.Post:
return "post";
default:
return "post";
}
}
So if no method value is supplied, then the method is defaulted to post.
However, it's worth me mentioning that when you specify null for the 3rd parameter, you're not actually setting the parameter method to null you're targeting the overload that has RouteValueDictionary as the third paramater, not the one with a FormMethod. This is because method is not a nullable parameter and RouteValueDictionary is an object which is nullable.
Html.BeginForm("Search", "YOUR CONTROLLER", null) calls overload:
public static MvcForm BeginForm(this HtmlHelper htmlHelper, string actionName, string controllerName, RouteValueDictionary routeValues);
Html.BeginForm("Search", "YOUR CONTROLLER", FormMethod.Post calls overload:
public static MvcForm BeginForm(this HtmlHelper htmlHelper, string actionName, string controllerName, FormMethod method);
You can see the source to this in Github at the following link: https://github.com/ASP-NET-MVC/aspnetwebstack/blob/4e40cdef9c8a8226685f95ef03b746bc8322aa92/src/System.Web.Mvc/HtmlHelper.cs

Instantiate a helper class but not in view

I need a way to instantiate a class thats supposed to help me with some querystring-building when it comes to my links in the view, and I cant use this methods that i require as static methods since that would cause the querystringbuilder to keep data during the whole life-time of the application (which would cause some serious problems)
So my question to you guys is,
Is it possible to some how be able to instantiate the class/object that i require but not in the actual view itself?
SO to keep the question simple.. is there anyway that I could do something like:
#MyInstantiatedObject.DoStuff()
in my view with out doing this before in my view:
#{
var MyInstantiatedObject = new MyClass()
}
I do get that I some where some how will need to instansiate the object, but my question is if its possible to do it in some other manner (like telling the web.config to handel it..or using some app_code #helper magic or something)
Thanks in advance!
What you are trying to achieve goes against the philosophy of MVC. If you want to keep the query string data between the actions, you can create your custom ActionLink html helper like this:
public static MvcHtmlString ActionLinkWithQueryString(this HtmlHelper htmlHelper,
string linkText, string actionName)
{
var routeValueDictionary = new RouteValueDictionary();
return htmlHelper.ActionLinkWithQueryString(linkText,
actionName, routeValueDictionary);
}
public static MvcHtmlString ActionLinkWithQueryString(this HtmlHelper htmlHelper,
string linkText, string actionName, RouteValueDictionary routeValues)
{
var queryString = HttpContext.Current.Request.QueryString;
if (queryString.Count > 0)
{
foreach (string key in queryString.Keys)
{
routeValues.Add(key, queryString[key]);
}
}
return htmlHelper.ActionLink(linkText, actionName, routeValues);
}
You can also create a custom RedirectToAction method in your Controller or in a Controller Extention like this:
private RedirectToRouteResult RedirectToActionWithQueryString(string actionName)
{
var queryString = Request.QueryString;
var routeValues = new RouteValueDictionary();
foreach (string key in queryString.Keys)
{
routeValues.Add(key, queryString[key]);
}
return RedirectToAction(actionName, routeValues);
}

The name 'Url' does not exist in the current context error

I have an MVC4 project that I am trying to create a helper for. I have added a folder called "App_Code", and in that folder I added a file called MyHelpers.cshtml. Here are the entire contents of that file:
#helper MakeButton(string linkText, string actionName, string controllerName, string iconName, string classes) {
Primary link
}
(I know there are some unused params, I'll get to those later after I get this fixed)
I "cleaned" and built the solution, no errors.
In the page that uses the helper, I added this code.
#MyHelpers.MakeButton("Back","CreateOffer","Merchant","","btn-primary")
When I attempt to run the project, I get the following error:
Compiler Error Message: CS0103: The name 'Url' does not exist in the
current context
I can't seem to find the correct way to write this - what am I doing wrong? It seems to be correct as compared to examples I've seen on the web?
As JeffB's link suggests, your helper file doesn't have access to the UrlHelper object.
This is an example fix:
#helper MakeButton(string linkText, string actionName,
string controllerName, string iconName, string classes) {
System.Web.Mvc.UrlHelper urlHelper =
new System.Web.Mvc.UrlHelper(Request.RequestContext);
<a href='#urlHelper.Action(linkText,actionName,controllerName)'
class="btn #classes">Primary link</a>
}
For my helpers I create a base class:
using System.Web.WebPages;
using System.Web.Mvc;
namespace MyProject
{
public class HelperBase : HelperPage
{
public static new HtmlHelper Html
{
get { return ((WebViewPage)WebPageContext.Current.Page).Html; }
}
public static System.Web.Mvc.UrlHelper Url
{
get { return ((WebViewPage)WebPageContext.Current.Page).Url; }
}
}
}
And then in my helper I do (to use yours as an example):
#inherits MyProject.HelperBase
#using System.Web.Mvc
#using System.Web.Mvc.Html
#helper MakeButton(string linkText, string actionName, string controllerName, string iconName, string classes) {
Primary link
}
Also, are you sure you didn't mean to use #Html.ActionLink (via LinkExtensions) instead of #Url.Action? The latter doesn't seem to have a linkText, actionName, controllerName overload, the former does?

HTML Encoding for HtmlHelper Extension Method

First of all I'm using MVC 3 RC1 with the Razor view engine. I've got an HTML helper extension which looks like this:
public static string TabbedMenuItem(this HtmlHelper htmlHelper, string text, string actionName, string controllerName) {
StringBuilder builder = new StringBuilder();
builder.Append("<li>");
builder.Append(text);
builder.Append("</li>");
return builder.ToString();
}
And on the view it's called like this:
#Html.TabbedMenuItem("Home", "Index", "Home")
The problem I've got is that MVC is automatically HTML encoding the result in the view so all I get is the encoded version of the string:
<li>Home</li>
Does anyone know how to disable the automatic encoding for your HTML helper extensions?
Thanks in advance
Andy
public static IHtmlString TabbedMenuItem(this HtmlHelper htmlHelper, string text, string actionName, string controllerName)
{
StringBuilder builder = new StringBuilder();
builder.Append("<li>");
builder.Append(text);
builder.Append("</li>");
return MvcHtmlString.Create(builder.ToString());
}
Use return value IHtmlString.
Hope this help.
Use TagBuilder

How do I access HtmlHelper methods from within MY OWN HtmlHelper?

I am writing my own HtmlHelper extenstion for ASP.NET MVC:
public static string CreateDialogLink (this HtmlHelper htmlHelper, string linkText,
string contentPath)
{
// fix up content path if the user supplied a path beginning with '~'
contentPath = Url.Content(contentPath); // doesn't work (see below for why)
// create the link and return it
// .....
};
Where I am having trouble is tryin to access UrlHelper from within my HtmlHelper's definition. The problem is that the way you normally access HtmlHelper (via Html.MethodName(...) ) is via a property on the View. This isn't available to me obviously from with my own extension class.
This is the actual MVC source code for ViewMasterPage (as of Beta) - which defines Html and Url.
public class ViewMasterPage : MasterPage
{
public ViewMasterPage();
public AjaxHelper Ajax { get; }
public HtmlHelper Html { get; }
public object Model { get; }
public TempDataDictionary TempData { get; }
public UrlHelper Url { get; }
public ViewContext ViewContext { get; }
public ViewDataDictionary ViewData { get; }
public HtmlTextWriter Writer { get; }
}
I want to be able to access these properties inside an HtmlHelper.
The best I've come up with is this (insert at beginning of CreateDialogLink method)
HtmlHelper Html = new HtmlHelper(htmlHelper.ViewContext, htmlHelper.ViewDataContainer);
UrlHelper Url = new UrlHelper(htmlHelper.ViewContext.RequestContext);
Am I missing some other way to access the existing HtmlHelper and UrlHelper instances - or do i really need to create a new one? I'm sure there isn't much overhead but I'd prefer to use the preexisting ones if I can.
Before asking this question I had looked at some of the MVC source code, but evidently I missed this, which is how they do it for the Image helper.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#", Justification = "The return value is not a regular URL since it may contain ~/ ASP.NET-specific characters")]
public static string Image(this HtmlHelper helper, string imageRelativeUrl, string alt, IDictionary<string, object> htmlAttributes) {
if (String.IsNullOrEmpty(imageRelativeUrl)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "imageRelativeUrl");
}
UrlHelper url = new UrlHelper(helper.ViewContext);
string imageUrl = url.Content(imageRelativeUrl);
return Image(imageUrl, alt, htmlAttributes).ToString(TagRenderMode.SelfClosing);
}
Looks like instantiating a new UrlHelper is the correct approach after all. Thats good enough for me.
Update: RTM code from ASP.NET MVC v1.0 Source Code is slightly different as pointed out in the comments.
File: MVC\src\MvcFutures\Mvc\ImageExtensions.cs
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#", Justification = "The return value is not a regular URL since it may contain ~/ ASP.NET-specific characters")]
public static string Image(this HtmlHelper helper, string imageRelativeUrl, string alt, IDictionary<string, object> htmlAttributes) {
if (String.IsNullOrEmpty(imageRelativeUrl)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "imageRelativeUrl");
}
UrlHelper url = new UrlHelper(helper.ViewContext.RequestContext);
string imageUrl = url.Content(imageRelativeUrl);
return Image(imageUrl, alt, htmlAttributes).ToString(TagRenderMode.SelfClosing);
}
I faced a similar issue and decided that it would be easier to just call the UrlHelper in the view and pass the output to my HtmlHelper extension. In your case it would look like:
<%= Html.CreateDialogLink( "text", Url.Content( "~/...path.to.content" ) ) %>
If you want to access the extension methods on the existing HtmlHelper that is passed into your class, you should only need to import System.Web.Mvc.Html in your source code file and you will get access to them (that's where the extension classes are defined). If you want a UrlHelper, you'll need to instantiate that as the HtmlHelper you are getting doesn't have a handle for the ViewPage that it's coming from.
If you need to create a UrlHelper in a utility class you can do the following :
string url = "~/content/images/foo.jpg";
var urlHelper = new UrlHelper(new RequestContext(
new HttpContextWrapper(HttpContext.Current),
new RouteData()), RouteTable.Routes);
string absoluteUrl = urlHelper.Content(url);
This allows you to use routing or '~ expansion' away from an MVC context.
Well, you can always pass the instance of the page to the extension method. I think that is a much better way of doing this than creating new instances in your method.
You could also define this method on a class that derives from MasterPage/ViewMasterPage and then derive the page from that. This way, you have access to all the properties of the instance and don't have to pass them around.

Resources