MVC Html Helper not being interpretend - html

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

How to load this large json file into objects or dataset using c#?

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

Adding a dynamic list of parameters with Html helper

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);

How to fetch content from namespace "Microsoft.AspNetCore.Mvc.Razor.HelperResult"

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)

how to create HTML Helper to extend TextBoxFor?

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);
}
}
}

render the view using razorengine mvc

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