I was trying out custom HTML Helpers in MVC 5, but they are not being interpreted in the browser. they come out as strings.
HTML Helper class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
public static class ImageHelper
{
public static string ImageLink(this HtmlHelper helper, string id, string imgSrc, string altText)
{
var builder = new TagBuilder("img");
builder.GenerateId(id);
builder.MergeAttribute("src", imgSrc);
builder.MergeAttribute("alt", altText);
return builder.ToString(TagRenderMode.SelfClosing);
}
}
HTML View
#Html.ImageLink("objStatus", "/images/circle-205-i.png", "status")
Browser display:
string "<img alt="status" id="objStatus" src="/images/circle-205-i.png" />"
F12 presents it as a string not interpreted as HTML
Your helper is returning a string which MVC Razor will encode as HTML. The correct way is to return an MvcHtmlString like this:
public static MvcHtmlString ImageLink(this HtmlHelper helper, string id, string imgSrc, string altText)
{
var builder = new TagBuilder("img");
builder.GenerateId(id);
builder.MergeAttribute("src", imgSrc);
builder.MergeAttribute("alt", altText);
return new MvcHtmlString(builder.ToString(TagRenderMode.SelfClosing));
}
An alternative is to use Html.Raw in your view, but you would have to do that everywhere. I only mention this here as it is possible to do and the above is the preferred solution.
Related
I'm relatively new to working with JSON and would like to deserialize content I downloaded from https://5e.tools/. I could try to anticipate all the tags/fields in a class, but the dataset example (https://www.newtonsoft.com/json/help/html/DeserializeDataSet.htm) looked more convenient so I tried that first:
using Newtonsoft.Json;
using System;
using System.Data;
using System.IO;
namespace _5EToolsConvertor
{
class Program
{
static void Main(string[] args)
{
string json = File.ReadAllText(#"D:\Downloads\5eTools.1.116.8\data\spells\spells-phb.json");
DataSet dataSet = JsonConvert.DeserializeObject<DataSet>(json);
DataTable dataTable = dataSet.Tables["spell"];
Console.WriteLine(dataTable.Rows.Count);
foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine(row["name"] + " - " + row["level"]); // just to check
}
}
}
}
Here is part of the first item from the JSON file:
{"spell":[{"name":"Acid Splash","source":"PHB","page":211,"srd":true,"level":0,"school":"C","time":[{"number":1,"unit":"action"}],"range":{"type":"point","distance":{"type":"feet","amount":60}},"components":{"v":true,"s":true},"duration":[{"type":"instant"}], ...
I get the error:
An unhandled exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll
Unexpected JSON token when reading DataTable: StartObject. Path 'spell[0].range', line 1, position 139.
EDIT 11/30/2020
Advice in the comments suggested moving from a dataset model (spreadsheet) because some of my JSON fields are hierarchical. I've created a class with List<Jobject> for the hierarchical fields like "Time". But, I'd rather end up with all data in vanilla c# objects like Dictionary<string, object>. I'm having trouble converting. What is the best way? This code runs on the full JSON file but prints System.Collections.Generic.List1[Newtonsoft.Json.Linq.JObject]` for every "Time" object.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
namespace _5EToolsConvertor
{
public class Spell
{
public string Name { get; set; }
public string Source { get; set; }
public string Page { get; set; }
public string SRD { get; set; }
public List<JObject> Time { get; set; }
}
class Program
{
static void Main(string[] args)
{
string jsontext = File.ReadAllText(#"D:\Downloads\5eTools.1.116.8\data\spells\spells-phb.json");
JObject json = JObject.Parse(jsontext);
// get JSON result objects into a list
IList<JToken> results = json["spell"].Children().ToList();
// serialize JSON results into .NET objects
IList<Spell> spells = new List<Spell>();
foreach (JToken item in results)
{
// JToken.ToObject is a helper method that uses JsonSerializer internally
Spell spell = item.ToObject<Spell>();
spells.Add(spell);
}
foreach (Spell spell in spells)
{
Console.WriteLine($"Name:{spell.Name} Source:{spell.Source} Page:{spell.Page} SRD:{spell.SRD} Time:{spell.Time}");
}
-david
I'd like to be able to feed in a list of parameter names and values into a Html.Actionlink but the helper doesn't create the parameters as I would like. Any ideas how to do this?
public class ParameterNameValue
{
public string ParameterName { get; set; }
public string ParameterValue { get; set; }
}
View
#foreach (var action in post.FeedActions)
{
var parameters = "";
foreach (var param in action.Parameters)
{
parameters += param.ParameterName + "=" + param.ParameterValue + ",";
}
#Html.ActionLink(#action.Label, action.ActionName,
new { controller = action.Controller, id = action.CommunityId, slug = action.Slug,
Fromfeed=true,parameters }, new { #class = action.Classes })
}
yields a link like this:
Whereas I need the parameters part to look like:
?FromFeed=true&MatchId=1234&InnerId=5678
edit: I got it working by just manually creating the tag, but no doubt there's a nice way of doing this by creating a custom helper.
#action.Label
I'd suggest you to extend the classic ActionLink helper with a prototype similar to this (add a parameter for your specific class) :
public static MvcHtmlString ActionLinkCustom(this HtmlHelper html, string linkText, string actionName, string controllerName, object routeValues, List<ParameterNameValue> yourOtherValues)
In the code, check if you got any custom values. If such, add them to the RouteValuesDictionnary. Then use the classic ActionLink helper providing this modified RouteValuesDictionnary.
Note : you can work on the routeValues using this
IDictionary<string, object> RouteValues = HtmlHelper.ObjectToDictionary(routeValues);
In ASP.NET Core, I need to fetch the content value from the namespace Microsoft.AspNetCore.Mvc.Razor.HelperResult and assign the value in a variable but its assigning the namespace to that variable.
It works fine in MVC when i use namespace System.Web.WebPages.HelperResult and assign that content to variable. (Content are some html elements).
Please, check the picture to find the issue.
My code:
Variable with namespace name as value
In .NET Core HelperResult returns IHtmlContent instead of IHtmlString.
For IHtmlContent it might be convenient to use an extension like the one mentioned here:
public static IHtmlContent GetList(this IHtmlHelper helper)
{
var listHtml = new HtmlContentBuilder();
listHtml.AppendHtml("<ol><li>");
listHtml.AppendHtml(helper.ActionLink("foo", "bar", "example"));
listHtml.AppendHtml("</li></ol>");
return listHtml;
}
Try this (since HelperResult implements IHtmlContent interface):
public static string ToHtmlString(this IHtmlHelper source, IHtmlContent htmlContent)
{
var sb = new StringBuilder();
using (TextWriter tw = new StringWriter(sb))
{
var encoder = (HtmlEncoder)source.ViewContext.HttpContext.RequestServices.GetService(typeof(HtmlEncoder));
htmlContent.WriteTo(tw, encoder);
}
return sb.ToString();
}
and call this method in your Razor view like this:
#Html.ToHtmlString(helperResultObject)
Hi I've got following line of code:
#Html.TextBoxFor(m => m.StartDate,"{0:MM/dd/yy hh:mm:ss}",new{#class="form-control axDateTimePicker"})
How to write helper to look like
#Html.DateTimePickerHelper(m=>m.StartDate)
where the format string and classes are inside this new helper?
For this you need to create custom html helpers by using extension method
Try the below code
namespace System.Web.Mvc
{
public static class CustomHtmlHelpers
{
public static MvcHtmlString DateTimePickerHelper<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
{
var attributes = new RouteValueDictionary(htmlAttributes);
string format = "{0:MM/dd/yy hh:mm:ss}";
return System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper, expression, format, attributes);
}
}
}
I am using RazorEngine to get the view and load it as html.but however my problem is I am reading html code from my database,and show it on my web page .but it gave me string result on my web page rather then html output.
how can I solve this problem
thank you in advace
My simple view like this
#model Cms.ViewModules.MasterPageViewModel
#Model.PageLanguageViewModel.HtmlCode
and this is how get the view as html from my views
public static class HtmlHelperPageContent
{
public static IHtmlString GetPageAll(this HtmlHelper htmlHelper, MasterPageViewModelmodel)
{
string page = model.PageLanguageViewModel.SablonHtlmCodu;
List<string> registeredModules = PageModulles.RegisteredModules;
foreach (var modulename in registeredModules )
{
string fullmodulename = "${" + modulename + "}";
if (page.Contains(fullmodulename ))
{
string viewname = modulename.Insert(0, "PW_");
IHtmlString value = RenderViewHelper.RenderPartialToString("Views/Default/" + viewname + ".cshtml", model);
page=page.Replace(fullmodulename , value.ToHtmlString());
}
}
return MvcHtmlString.Create(page);
}
RenderViewHelper class
public static class RenderViewHelper
{
public static IHtmlString RenderPartialToString(string viewPath, object model)
{
string viewAbsolutePath = MapPath(viewPath);
var viewSource = File.ReadAllText(viewAbsolutePath);
string renderedText = Razor.Parse(viewSource, model);
return new MvcHtmlString(renderedText);
}
}
Another way would be to use IEncodedString (https://github.com/Antaris/RazorEngine/blob/master/src/source/RazorEngine.Core/Text/IEncodedString.cs) instead of IHtmlString by creating a RawString (https://github.com/Antaris/RazorEngine/blob/master/src/source/RazorEngine.Core/Text/RawString.cs) instance.
#Raw does exactly that behind the scenes (https://github.com/Antaris/RazorEngine/blob/master/src/source/RazorEngine.Core/Templating/TemplateBase.cs#L147).
#Raw(#Model.PageLanguageViewModel.HtmlCode) solved my problem