System.Web.Mvc.HtmlHelper' does not contain a definition for 'ActionLink' - asp.net-mvc-3

I would like to use custom #Html.ActionLink
I am trying to use the following code:-
public static class LinkExtensions
{
public static MvcHtmlString MyActionLink(
this HtmlHelper htmlHelper,
string linkText,
string action,
string controller)
{
var currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
var currentController = mlHelper.ViewContext.RouteData.GetRequiredString("controller");
if (action == currentAction && controller == currentController)
{
var anchor = new TagBuilder("a");
anchor.Attributes["href"] = "#";
anchor.AddCssClass("currentPageCSS");
anchor.SetInnerText(linkText);
return MvcHtmlString.Create(anchor.ToString());
}
return htmlHelper.ActionLink(linkText, action, controller);
}
}
From Custom ActionLink helper that knows what page you're on
But I am getting
System.Web.Mvc.HtmlHelper' does not contain a definition for
'ActionLink' and no extension method 'ActionLink' accepting a first
argument of type 'System.Web.Mvc.HtmlHelper' could be found (are you
missing a using directive or an assembly reference?

Add this using System.Web.Mvc.Html; on top of your file

Make sure you have the namespace for your extensions class included in your web.config. For example:
namespace MyProject.Extensions
{
public static class LinkExtensions
{
//code
}
}
In your site Web.config and/or Web.config located in your "Views" folder:
<system.web>
<pages>
<namespaces>
<add namespace="MyProject.Extensions" />
</namespaces>
</pages>
</system.web>
Otherwise include a "using" block for the namespace at the top of your view page can work but for common namespaces I would do the above.
ASPX:
<%# Import namespace="MyProject.Extensions" %>
RAZOR:
#using MyProject.Extensions

Don't forget that the first parameter only accepts string. It will show you this error if it's NOT.

Make sure that you have following using in your class file:
using System.Web.Mvc.Html;
This is needed because the HtmlHelper class is located in System.Web.Mvc namespace but the ActionLink extension method is located in System.Web.Mvc.Html namespace.

If your using nopcommerce add this using statement at the top of your view file.
#using Nop.Web.Framework.UI

My issue was, I had incomplete syntax, "#Html.actionLink", in a view. Looks like I had started to add an action link and went a different direction but forgot to remove the partial action link, this caused the same error as above.... So check your syntax as that will throw the same runtime error. Good luck!

Related

Link in validation summary message

Is it possible to put a HTML link in validation summary message? For example I want to put a link to another page in case there is validation error:
#Html.ValidationSummary(False, "read more")
or
#Html.ValidationSummary(False, "read " &
Html.ActionLink("more", "helpforerror").ToHtmlString)
But in the browser the tag is escaped so it doesn't form a link.
I know you have accepted an answer, but i think my solution is more simple and will require less rewriting if you want to add links to existing validation summaries.
You need to put a {0} type format item in your validation message like below, which will be replaced by your link.
ModelState.AddModelError("", "Some error message with a link here {0}.");
then in your view call your validation summary like so:
#string.Format(Html.ValidationSummary().ToString(), Html.ActionLink("Click Here", "Action_To_Link_To")).ToHtmlString()
In this case i have used an extension method I added to the string object .ToHtmlString() that basically just converts the string to an HtmlString preventing any of the markup being escaped. it looks like this:
public static HtmlString ToHtmlString(this String str)
{
return new HtmlString(str);
}
Finally I chose another way to do it: create a div containing the link etc. outside of validation summary, and add the div only if modelstate is not valid:
#If Not ViewData.ModelState.IsValid Then
#<div>read more</div>
End If
This is inspired by an answer to similar question.
The validation text is encoded before the ValidationSumary or ValidationFor, etc...
you just need tu decode the html, then create an MvcHtmlString ...
Exemple :
#HttpUtility.HtmlDecode(Html.ValidationSummary().ToString()).ToMvcHtmlString()
this is an extension i have made to make MvcHtmlString :
namespace System
{
public static class StringExtension
{
public static System.Web.Mvc.MvcHtmlString ToMvcHtmlString(this string value)
{
return System.Web.Mvc.MvcHtmlString.Create(value);
}
}
}
or you can create an HtmlHelper if you plan to reuse this:
namespace System.Web.Mvc.Html
{
public static class FormHelper
{
public static MvcHtmlString ValidationSummaryEx(this HtmlHelper htmlHelper, bool excludePropertyErrors)
{
var original = htmlHelper.ValidationSummary(excludePropertyErrors);
var decoded = HttpUtility.HtmlDecode(original.ToString());
return decoded.ToMvcHtmlString();
}
}
}
Hope it help you or future viewer.
Note: it work for all validations Summary and ValidationFor ...
No, the default behaviour doesn't allow it, but you can make your own. This is what you need: Html raw in validationsummary
You can check if form is valid by jquery and update div with link text:
<div id="divToUpdate">
</div>
$('form').submit(function(){
if(!this.valid())
$('#divToUpdate').html("read <a href='anotherpage.html'>more</a>");
});
If you're sending back HTML in the ModelStateError, you can use this one liner:
#Html.Raw(HttpUtility.HtmlDecode(Html.ValidationSummary().ToHtmlString()))
It's very similar to what #Benoit had suggested, just without needing the extension.

ValidateRequest in Razor syntax

I have the following header of ASP.Net MVC page:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Admin.Master" Inherits="System.Web.Mvc.ViewPage<NEOGOV_Ideas.Models.SubIdeaAdminPage>"
ValidateRequest="false" %>
I need to move this page to Razor syntax. How should I set ValidateRequest?
Thanks
Decorate your action method with ValidateInput attribute
[HttpPost]
[ValidateInput(false)]
public ActionResult index()
{
return view();
}
You shouldn't need that line in the view, instead use the ValidateInput(false) attribute on the controller method.
Make sure you've got this in your web.config if you're using ASP .net 4.0 (which I presume you are if you're using MVC 3)
<httpRuntime requestValidationMode="2.0"/>
Martin
From MVC 4 we can allow html content only for property of model class, not for the whole request. Just need to mark property by attribute AllowHtml
public class EditorialPixlocateRequestViewModel
{
[AllowHtml]
public string Xml { get; set; }
}

MVC (Razor) Helper Class (ValidationImage) not rendering/working?

I am trying to use the following helper class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using System.Web.Mvc;
using System.Web.Routing;
namespace myNamespace
{
public static class ValidationHelper
{
public static MvcHtmlString ValidationImage(this HtmlHelper helper, string name)
{
if (helper.ViewData.ModelState[name] == null || helper.ViewData.ModelState[name].Errors == null || helper.ViewData.ModelState[name].Errors.Count == 0)
{
return MvcHtmlString.Empty;
}
var tag = new TagBuilder("img");
tag.Attributes.Add("src", "../Content/Images/check_bg_invalid.png");
tag.Attributes.Add("alt", helper.ViewData.ModelState[name].Errors[0].ErrorMessage);
tag.Attributes.Add("title", helper.ViewData.ModelState[name].Errors[0].ErrorMessage);
tag.Attributes.Add("class", HtmlHelper.ValidationMessageCssClassName);
return MvcHtmlString.Create(tag.ToString(TagRenderMode.SelfClosing));
}
}
}
And using this in a view:
#Html.ValidationImage("FirstName")
to try and get an image to fire when there is a validation error.
So I have my:
#Html.TextBox("FirstName", null, new { #class = "my_input" })
in the same view (all within the #Html.BeginForm)
This is my model.cs class:
public class QuoteModel
{
[Required(ErrorMessage = "You must specify a First Name.")]
public string First Name { get; set; }
}
And this is my controller.cs class:
public ActionResult Quote()
{
//return View();
var model = new QuoteModel();
return View(model);
}
[HttpPost]
public ActionResult Quote(QuoteModel model)
{
if (ModelState.IsValid)
{
try
{
}
catch (Exception)
{
return View(model);
}
}
return RedirectToAction("QuoteSuccess");
}
public ViewResult QuoteSuccess()
{
return View();
}
Bear in mind, I may have made a typo in all of the preceding code blocks.
Originally, I used
#Html.ValidationMessage("FirstName")
and the Error Message would fire after clicking send. I am trying to now use the above helper for ValidationImage, but nothing fires (and the Error Message doesn't show). Nor is anything output with an <img> tag. No errors are thrown on the page.
As an aside, I have two other questions:
1) I would also like to display a validation success message (i.e., a little image with "OK"), but am having trouble just getting above to work in the first instance.
2) I was previously unsuccessful (before using helper) to get client side validation to show.
Am using
#{ Html.EnableClientValidation(); }
in that same view. I placed it at the top (after #model). Does placement matter?
I also used the following in my _layout.cshtml
<script language="javascript" src="#Url.Javascript("jquery.validate.min")" type="text/javascript"></script>
<script language="javascript" src="#Url.Javascript("jquery.validate.unobtrusive.min")" type="text/javascript"></script>
Note that I use a helper, so no need for ".js" extension - this has worked in the past and shows up in view source. So no problems there.
Finally, I do have my web.config set up thusly:
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
Any thoughts on either of my problems (particularly the main one) are much appreciated.
It looks to me like your validation image will only be output in the page if the server-side validation fails. This means your client-side validation can't possibly show the image, as it won't exist in the HTML markup (return MvcHtmlString.Empty;)
If you want the validation to work client-side (and show the image), you might have to do some work to hook into the existing validation. There's an article here about custom validation:
http://www.codeproject.com/Articles/98376/Including-custom-client-side-validations-in-your-A.aspx
Though it might be a little overly complicated - there may be an easier way to hook into it (though I can't find one just now).

How do you include .html or .asp file using razor?

Is it possible to use server side include in Razor view engine to include .html or .asp file? We have an .html file and .asp files that contain website menus that are used for all of our websitse. Currently we use server side include for all of our sites so that we only need to change the mensu in one place.
I have the following code in the body of my _Layout.cshtml
<body>
<!--#include virtual="/serverside/menus/MainMenu.asp" -->
<!--#include virtual="/serverside/menus/library_menu.asp" -->
<!--#include virtual="/portfolios/serverside/menus/portfolio_buttons_head.html" -->
#RenderBody()
</body>
Instead of including the content of the file, if I do a view source, I see the literal text.
" <!--#include virtual="/serverside/menus/MainMenu.asp" -->
<!--#include virtual="/serverside/menus/library_menu.asp" -->
<!--#include virtual="/portfolios/serverside/menus/portfolio_buttons_head.html" -->"
#Html.Raw(File.ReadAllText(Server.MapPath("~/content/somefile.css")))
Try making your html page to a cshtml page and including it with:
#RenderPage("_header.cshtml")
Try implementing this HTML helper:
public static IHtmlString ServerSideInclude(this HtmlHelper helper, string serverPath)
{
var filePath = HttpContext.Current.Server.MapPath(serverPath);
// load from file
using (var streamReader = File.OpenText(filePath))
{
var markup = streamReader.ReadToEnd();
return new HtmlString(markup);
}
}
or:
public static IHtmlString ServerSideInclude(this HtmlHelper helper, string serverPath)
{
var filePath = HttpContext.Current.Server.MapPath(serverPath);
var markup = File.ReadAllText(filePath);
return new HtmlString(markup);
}
#RenderPage("PageHeader.cshtml")
<!-- your page body here -->
#RenderPage("PageFooter.cshtml")
This works just fine and can save you a lot of time.
Razor does not support server-side includes. The easiest solution would be copying the menu markup into your _Layout.cshtml page.
If you only needed to include .html files you could probably write a custom function that read the file from disk and wrote the output.
However since you also want to include .asp files (that could contain arbitrary server-side code) the above approach won't work. You would have to have a way to execute the .asp file, capture the generated output, and write it out to the response in your cshtml file.
In this case I would go with the copy+paste approach
Create a HtmlHelper extension method that gets the contents of the files:
public static class HtmlHelpers
{
public static MvcHtmlString WebPage(this HtmlHelper htmlHelper, string url)
{
return MvcHtmlString.Create(new WebClient().DownloadString(url));
}
}
Usage:
#Html.WebPage("/serverside/menus/MainMenu.asp");
Sorry guys for bit old answer but I found some way to attach asp file with razor. Of course you need to do some trick but it works! First of all I created .NET MVC 3 application.
In my _Layout.cshtml I added following line:
#Html.Partial("InsertHelper")
Then I created InsertHelper.aspx in my Shared folder with this content:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<!--#include VIRTUAL="/ViewPage1.aspx"-->
ViewPage1.aspx is locaited in my root directory, and has just simple if to check whether it works:
<%
string dummy;
dummy="nz";
%>
<% if (dummy == "nz") { %>
nz indeed
<% } else { %>
not nz
<% } %>
And it works!
Razor is able to render partials with different ViewEngine, and that's why this example is working.
And one more thing: remember to not add following line in both aspx files:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
You can add it only once! Hope it helps!
I had the same issue when I tried to include an .inc file in MVC 4.
To solved this issue, I changed the suffix of the file to .cshtml and I added the following line
#RenderPage("../../Includes/global-banner_v4.cshtml")
Just do:
#Html.Partial("_SliderPartial")
while "_SliderPartial" is your "_SliderPartial.cshtml" file and your fine.
In my _Layout.cshtml I added following line:
#Html.Partial("InsertHelper")
Then I created InsertHelper.aspx in my Shared folder with this content:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<!--#include VIRTUAL="/ViewPage1.aspx"-->
Why not include a section within your _Layout.cshtml page that will allow you to render sections based on what menu you want to use.
_Layout.cshtml
<!-- Some stuff. -->
#RenderSection("BannerContent")
<!-- Some other stuff -->
Then, in any page that uses that layout, you will have something like this:
#section BannerContent
{
#*Place your ASP.NET and HTML within this section to create/render your menus.*#
}
Html.Include(relativeVirtualPath) Extension Method
I wanted to include files like this for documentation purposes (putting the contents of a file in a <pre> tag).
To do this I added an HtmlHelperExtension with a method that takes a relative virtual path (doesn't have to be an absolute virtual path) and an optional boolean to indicate whether you wish to html encode the contents, which by default my method does since I'm using it primarily for showing code.
The real key to getting this code to work was using the VirtualPathUtility as well as the WebPageBase. Sample:
// Assume we are dealing with Razor as WebPageBase is the base page for razor.
// Making this assumption we can get the virtual path of the view currently
// executing (will return partial view virtual path or primary view virtual
// path just depending on what is executing).
var virtualDirectory = VirtualPathUtility.GetDirectory(
((WebPageBase)htmlHelper.ViewDataContainer).VirtualPath);
Full HtmlHelperExtension Code:
public static class HtmlHelperExtensions
{
private static readonly IEnumerable<string> IncludeFileSupportedExtensions = new String[]
{
".resource",
".cshtml",
".vbhtml",
};
public static IHtmlString IncludeFile(
this HtmlHelper htmlHelper,
string virtualFilePath,
bool htmlEncode = true)
{
var virtualDirectory = VirtualPathUtility.GetDirectory(
((WebPageBase)htmlHelper.ViewDataContainer).VirtualPath);
var fullVirtualPath = VirtualPathUtility.Combine(
virtualDirectory, virtualFilePath);
var filePath = htmlHelper.ViewContext.HttpContext.Server.MapPath(
fullVirtualPath);
if (File.Exists(filePath))
{
return GetHtmlString(File.ReadAllText(filePath), htmlEncode);
}
foreach (var includeFileExtension in IncludeFileSupportedExtensions)
{
var filePathWithExtension = filePath + includeFileExtension;
if (File.Exists(filePathWithExtension))
{
return GetHtmlString(File.ReadAllText(filePathWithExtension), htmlEncode);
}
}
throw new ArgumentException(string.Format(
#"Could not find path for ""{0}"".
Virtual Directory: ""{1}""
Full Virtual Path: ""{2}""
File Path: ""{3}""",
virtualFilePath, virtualDirectory, fullVirtualPath, filePath));
}
private static IHtmlString GetHtmlString(string str, bool htmlEncode)
{
return htmlEncode
? new HtmlString(HttpUtility.HtmlEncode(str))
: new HtmlString(str);
}
}
you can include server side code and aspx file in .cshtml files as below and then inlude classic asp files or html files.
Here are the steps
Index.cshtml
#Html.RenderPartial("InsertASPCodeHelper")
2.InsertASPCodeHelper.aspx
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<!--#include VIRTUAL="~/Views/Shared/Header.aspx"-->
Header.aspx
<!--#include file="/header/header.inc"-->
Using includes is not the correct way to use menus with mvc. You should be using a shared layout and/or partial views.
However if for some odd reason, you must include an html file, here is a way to do it.
Helpers/HtmlHelperExtensions.cs
using System.Web;
using System.Web.Mvc;
using System.Net;
namespace MvcHtmlHelpers
{
public static class HtmlHelperExtensions
{
public static MvcHtmlString WebPage(this HtmlHelper htmlHelper, string serverPath)
{
var filePath = HttpContext.Current.Server.MapPath(serverPath);
return MvcHtmlString.Create(new WebClient().DownloadString(filePath));
}
}
}
Add new namespace to web.config
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="MvcHtmlHelpers"/>
</namespaces>
</pages>
Usage:
#Html.WebPage("/Content/pages/home.html")

MVC3 UrlHelperExtensions with Razor Views (from .ASPX)

I looked through everything I could find on Razor Views, but I could not find anything on how to convert this UrlHelper usage to Razor from WebForms.
.ASPX Code Sample:
<img src="<%= Url.AccountPicture(Model.Picture, "bigger") %>" alt="<%= Html.AttributeEncode(Model.FullName) %>" width="73" height="73" />
How I converted it to RAZOR:
<img src="#Url.AccountPicture(Model.Picture, "bigger")" alt="#Html.AttributeEncode(Model.FullName)" width="73" height="73" />
The UrlHelperExtensions.cs File that goes with it:
namespace ShadowVenue.Extensions
{
public static class UrlHelperExtensions
{
public static string AccountPicture(this UrlHelper helper, string name, string size)
{
if (string.IsNullOrEmpty(name))
name = "default";
return helper.Content(string.Format("~/content/images/pictures/{0}_{1}.png", name, size));
}
}
}
Error That Visual Studio Highlights |#Url.AccountPicture| with:
'System.Web.Mvc.UrlHelper' does not contain a definition for 'AccountPicture' and no extension method 'AccountPicture' accepting a first argument of type 'System.Web.Mvc.Helper' could be found (are you missing a using directive or assembly reference?)
It Produces This Error on RunTime:
'System.Web.Mvc.UrlHelper' does not contain a definition for 'AccountPicture' and no extension method 'AccountPicture' accepting a first argument of type 'System.Web.Mvc.UrlHelper' could be found (are you missing a using directive or an assembly reference?)
I have namespace ShadowVenue.Extensions registed in the web.config
Please Help, Thank You!
You need to include the ShadowVenue.Extensions namespace in the <system.web.webPages.razor> tag (not the <pages> tag).
In addition to SLaks' answer, you could put a #using ShadowVenue.Extensions tag at the top of your razor view for a one-off reference.

Resources