How do you render a list of components in a loop (Blazor)? - razor

I must be missing something very obvious with blazor... I want to simply render a list containing a component, yet there's no (obvious?) way to reference the iterator (which is a component) for rendering?
TodoList.razor
<input #bind="_newTodo" />
<button #onclick="#AddTodoItem">+</button>
#foreach (TodoItem todoItem in _todoItems)
{
// todoItem is a razor component, yet I can't simply render it here?
// <todoItem />
}
#code {
private IList<TodoItem> _todoItems = new List<TodoItem>();
private string _newTodo;
private void AddTodoItem()
{
if (!string.IsNullOrWhiteSpace(_newTodo))
{
_todoItems.Add(new TodoItem { Title = _newTodo });
_newTodo = string.Empty;
}
}
}
TodoItem.razor
<span>#Title</span>
#code {
public string Title { get; set; }
}

One solution to do that is have a class that holds the component properties and pass the properties to it
<input #bind="_newTodo" />
<button #onclick="#AddTodoItem">+</button>
#foreach (TodoItem todoItem in _todoItemsDto)
{
// Pass the Dto properties to the component
<TodoItem Title="#todoItem.Title" />
}
#code {
private IList<TodoItemDto> _todoItemsDto = new List<TodoItemDto>();
private string _newTodo;
class TodoItemDto {
public string Title { get; set; }
}
private void AddTodoItem()
{
if (!string.IsNullOrWhiteSpace(_newTodo))
{
_todoItems.Add(new TodoItemDto { Title = _newTodo });
_newTodo = string.Empty;
}
}
}

I just built a Help system that has a LinkButton component, and I render it like this:
foreach (HelpCategory category in Categories)
{
<LinkButton Category=category Parent=this></LinkButton>
<br />
}
Each HelpCategory has one or more Help Articles that can be expanded.
Here is the code for my LinkButton, it does more of the same:
#using DataJuggler.UltimateHelper.Core
#using ObjectLibrary.BusinessObjects
#if (HasCategory)
{
<button class="linkbutton"
#onclick="SelectCategory">#Category.Name</button>
#if (Selected)
{
<div class="categorydetail">
#Category.Description
</div>
<br />
<div class="margintop">
#if (ListHelper.HasOneOrMoreItems(Category.HelpArticles))
{
foreach (HelpArticle article in Category.HelpArticles)
{
<ArticleViewer HelpArticle=article Parent=this>
</ArticleViewer>
<br />
<div class="smallline"></div>
}
}
</div>
}
}

Sometimes the obvious solutiton is simpler and better.
TodoItem:
<span>#Title</span>
#code {
[Parameter] // add this parameter to accept title
public string Title { get; set; }
}
Page:
<input #bind="_newTodo"/>
<button #onclick="#AddTodoItem">+</button>
<ol>
#foreach (var todoItem in _todoItems)
{
<li>
<TodoItem Title="#todoItem.Title"/>
</li>
}
</ol>
#code {
private readonly IList<TodoItem> _todoItems = new List<TodoItem>();
private string _newTodo;
private void AddTodoItem()
{
if (!string.IsNullOrWhiteSpace(_newTodo))
{
_todoItems.Add(new TodoItem { Title = _newTodo });
_newTodo = string.Empty;
}
}
}
Output:

This may not be the best way to do it but it will avoid having 50+ attributes to set in the tag.
Component :
<h1>#Title</h1>
<h2>#Description</h2>
#code {
public string? Title { get; set; }
public string? Description { get; set; }
[Parameter]
public KanbanTask? Origin //KanbanTask is how I named this same component
{
get { return null; }
set
{
Title = value?.Title;
Description = value?.Description;
}
}
}
Then how to call it :
#foreach (var todoTask in TodoList)
{
<KanbanTask Origin="#todoTask" />
}
This is using the set of a property has a constructor. It works, but I think it's not excellent since set was not made for it in the first instance. If anyone else has an idea to make it better I'm interested

Yes, of course you can render a list with foreach. This article covers it well.
Here is an example. Note the use of the item in the click event so you know which item was clicked on. Note that this must be done using a lambda.
<section data-info="List of images">
#foreach (var item in this.Parent.CurrentCard.Images.OrderByDescending(a => a.InsertedDate))
{
<div class="border border-secondary m-2">
<img class="img-fluid" src="/api/image/fetch/#item.StorageName" alt="#item. Filename">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
Remove
</div>
</div>
}

Related

ASP.NET Core : creating form input for model property of type List

I have been searching online for an answer to this specific issue but I can't seem to find it.
I am currently creating a form using Razor pages and cannot find out how to create a form input that would be able to take multiple values for one item in the form. Below I will post a quick example of what I mean.
Current issues: when I add another input programmatically it will only add 2 maximum and will not send a value
Model:
public class FormInput
{
public List<Address> Addresses { get; set; }
public List<Category> Categories { get; set; }
}
Razor Page:
public class FormPage : PageModel
{
[BindProperty] public FormInput _Input { get; set; }
}
HTML Page:
<form>
<ul class="Category-Container">
<li>
<input asp-for="_Input.Addresses" type="text" />
<button type="button" onclick="this.AddCategory">
Add New Address
</button>
</li>
</ul>
<div>
<input asp-for="_Input.Categories" type="text" />
<button type="button" onclick="this.AddNewInput">
Add New Category
</button>
</div>
</form>
Javascript:
var categoryContainer = document.getElementById("Category-Container");
function AddCategory() {
var input = document.createElement("input");
input.classList.add("w-100");
input.name = "BusinessCategory";
var inputCol = document.createElement("div");
inputCol.classList.add("col-8");
inputCol.appendChild(input);
var btn = document.createElement("button");
btn.classList.add("btn");
btn.classList.add("btn-primary");
btn.innerText = "Add New Category";
var btnCol = document.createElement("div");
btnCol.classList.add("col");
btnCol.appendChild(btn);
var row = document.createElement("li");
row.classList.add("row");
var part1 = row.appendChild(inputCol);
var part2 = part1.appendChild(btnCol);
categoryContainer.appendChild(part2);
}
There's a little disconnect in the javascript function but you can assume that the Button and the Input in the HTML example are inside of Columns also, i don't think that makes a big difference but please let me know if it would be one
Tag helper cannot pass complex model type data to backend, it only allows simple type. That is to say, you need set the model's property name in asp-for.
Then, if you want to get the list model, you need specific the list index like: _Input.Categories[0].PropertyName.
Not sure what is your whole view, here is a simple demo about how to pass list model to backend:
Model:
public class FormInput
{
public List<Address> Addresses { get; set; }
public List<Category> Categories { get; set; }
}
public class Address
{
public string Name { get; set; }
}
public class Category
{
public string BusinessCategory { get; set; }
}
View:
#page
#model IndexModel
<form method="post">
<ul id="Category-Container">
<li>
<input asp-for="_Input.Categories[0].BusinessCategory" type="text" />
<button type="button" onclick="AddCategory()">
Add New Address
</button>
</li>
</ul>
<div>
<input asp-for="_Input.Addresses[0].Name" type="text" />
<button type="button" onclick="this.AddNewInput">
Add New Category
</button>
</div>
<input type="submit" value="Post"/>
</form>
JS:
#section Scripts
{
<script>
var count = 1; //add count...
var categoryContainer = document.getElementById("Category-Container");
function AddCategory() {
var input = document.createElement("input");
input.classList.add("w-100");
//change the name here.....
input.name = "_Input.Categories["+count+"].BusinessCategory";
var inputCol = document.createElement("div");
inputCol.classList.add("col-8");
inputCol.appendChild(input);
var btn = document.createElement("button");
btn.classList.add("btn");
btn.classList.add("btn-primary");
btn.innerText = "Add New Category";
var btnCol = document.createElement("div");
btnCol.classList.add("col");
btnCol.appendChild(btn);
var row = document.createElement("li");
row.classList.add("row");
var part1 = row.appendChild(inputCol);
part1.appendChild(btnCol); //change here...
categoryContainer.appendChild(part1); //change here...
count++; //add here ...
}
</script>
}
Backend code:
public class IndexModel: PageModel
{
[BindProperty] public FormInput _Input { get; set; }
public IActionResult OnGet()
{
return Page();
}
public void OnPost()
{
}
}

My Wicket TabbedPanel doesn't keep the form field values

I'm new using Apache Wicket. I'm creating a panel to add articles on a web site. My panel to edit an article is formed with a TabbedPanel: the first tab is to edit and the second tab is to preview the article.
If after I entered some text in the editor (textarea), I switch to the preview and go back to the editor, le textarea is empty.
Here a part of the code for the panel with the TabbedPanel:
public AddArticlePanel(String id, ArticleEdit articleEdit) {
super(id);
final List<AbstractTab> tabList = new ArrayList<>();
tabList.add(new AbstractTab(new Model<String>("Editor")) {
#Override
public WebMarkupContainer getPanel(String panelId) {
return new ArticleEditorPanel(panelId, articleEdit);
}
});
tabList.add(new AbstractTab(new Model<String>("Preview")) {
#Override
public WebMarkupContainer getPanel(String panelId) {
return new ArticlePreviewPanel(panelId, articleEdit);
}
});
tabs = new TabbedPanel<AbstractTab>("tabs", tabList);
final SubmitLink submitButton = new SubmitLink("submit") {
#Override
public void onSubmit() {
// TODO
}
};
addArticleForm = new Form<ArticleEdit>("add-article-form", new Model<ArticleEdit>(articleEdit));
addArticleForm.add(tabs);
addArticleForm.add(submitButton);
add(addArticleForm);
}
Here the HTML for the editor panel:
<wicket:panel>
<div wicket:id="feedback"></div>
<div class="fields">
<label for="title">Title</label>
<input type="text" name="title" wicket:id="title">
</div>
<div class="fields">
<label for="text">Text</label>
<textarea class="notab" name="text" wicket:id="text"></textarea>
</div>
<div class="fields">
<label for="keywords">Keywords</label>
<input type="text" name="keywords" wicket:id="keywords">
</div>
</wicket:panel>
The code for this editor panel:
public ArticleEditorPanel(String id, ArticleEdit articleEdit) {
super(id);
final FeedbackPanel feedbackPanel = new FeedbackPanel("feedback");
title = new TextField<String>("title", new PropertyModel<String>(articleEdit, "title"));
title.setRequired(true);
text = new TextArea<String>("text", new PropertyModel<String>(articleEdit, "text"));
text.setRequired(true);
keywords = new TextField<String>("keywords", new PropertyModel<String>(articleEdit, "keywords"));
keywords.setRequired(true);
add(title);
add(text);
add(keywords);
add(feedbackPanel);
}
Finally, the source code of the ArticleEdit class:
public class ArticleEdit implements Serializable {
private String title;
private String text;
private String keywords;
private String preview;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getKeywords() {
return keywords;
}
public void setKeywords(String keywords) {
this.keywords = keywords;
}
public String getPreview() {
return preview;
}
public void setPreview(String preview) {
this.preview = preview;
}
}
Why it doesn't work out of the box ? Where is my mistake ?
Thank you for your help.
You do not save the state from your EDIT tab before navigating to the PREVIEW tab.
By clicking the "Preview" link the browser will make a new request to the server and Wicket will re-render the whole page, so any data entered in the form fields will be lost.
You can easily save the data by adding AjaxFormComponentUpdatingBehavior to the form fields. For example for the title field:
title = new TextField<String>("title", new PropertyModel<String>(articleEdit, "title"));
title.setRequired(true);
title.add(new AjaxFormComponentUpdatingBehavior("change") {
#Override public void onUpdate(AjaxRequestTarget target) {}
#Override public void onError(AjaxRequestTarget target) {
target.add(feedbackPanel);
}
});

Passing wrong model into partial

I am building my first web app with .net core razor pages.
I am trying to move my menu to be partial, so I can reuse it as I wish but I must be doing something wrong.
The error is:
The model item passed into the ViewDataDictionary is of type 'BrambiShop.UI.Pages.IndexModel', but this ViewDataDictionary instance requires a model item of type 'BrambiShop.UI.Pages.Shared._SideCategoriesMenuModel'.
I know there are few topics on that, but I am struggling " days after work now and I couldnt find any exact solution. I quess I kinda understand what I am doing wrong. But I dont know how to do it right.
I am trying to load the partial from index as follows:
#page
#model IndexModel
#{
ViewData["Title"] = "Home page";
}
#{ await Html.RenderPartialAsync("_SideCategoriesMenu"); }
The partial is:
#page
#model BrambiShop.UI.Pages.Shared._SideCategoriesMenuModel
#*
For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
*#
#foreach (var category in Model.Categories)
{
<button class="font-weight-bold" data-toggle="collapse" href="#MenuCollapse_#Html.DisplayFor(modelItem => category.Id)"
aria-expanded="false" aria-controls="MenuCollapse_#Html.DisplayFor(modelItem => category.Id)">
#Html.DisplayFor(modelItem => category.Name)
</button>
<!-- Collapsible element -->
<div class="collapse text-center" id="MenuCollapse_#Html.DisplayFor(modelItem => category.Id)">
#foreach (var subCategory in Model.SubCategories.Where(x => x.CategoryId == category.Id))
{
<form action="/url/to/action" Method="GET">
<input type="hidden" name="Property" value="#Html.DisplayFor(modelItem => subCategory.Id)" />
<button type="submit">
<i class="fas fa-caret-right pl-1"></i>#Html.DisplayFor(modelItem => subCategory.Name)
</button>
</form>
}
</div>
<!-- / Collapsible element -->
}
And at last the cshtml.cs
using BrambiShop.API.Models;
using BrambiShop.UI.Services;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace BrambiShop.UI.Pages.Shared
{
public class _SideCategoriesMenuModel : PageModel
{
private readonly IApiClient _Client;
public _SideCategoriesMenuModel(IApiClient client)
{
_Client = client;
}
public IList<Category> Categories { get; set; }
public IList<SubCategory> SubCategories { get; set; }
public async Task OnGet()
{
Categories = await _Client.GetCategoriesAsync();
SubCategories = await _Client.GetSubCategoriesAsync();
}
}
}
Can someone help me with that please? I did watch about 10 hours of tutorials to build api and the ground of the web, but this damn partial. I just cant find answer to that anywhere.
Thank you very much for any effort.
EDIT
--- index model
using BrambiShop.API.Models;
using BrambiShop.UI.Services;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace BrambiShop.UI.Pages
{
public class IndexModel : PageModel
{
public IndexModel()
{
}
public async Task OnGet()
{
}
}
}
Your Index view has a model of type IndexModel. When you put this line
#{ await Html.RenderPartialAsync("_SideCategoriesMenu"); }
The same model will be passed to _SideCategoriesMenu which is IndexModel. This is why you are receiving the exception because the model passed to the _SideCategoriesMenu is different since it expects BrambiShop.UI.Pages.Shared._SideCategoriesMenuModel.
To go around that, you have to specify the model in the RenderPartialAsync method. ex:
#{ await Html.RenderPartialAsync("_SideCategoriesMenu",YOUR_MODEL_HERE); }
You can replace YOUR_MODEL_HERE with whatever instance of type _SideCategoriesMenuModel. You can have it as a property inside IndexModel. ex:
public class IndexModel : PageModel
{
public IndexModel()
{
}
public SideMenuModel SideMenu { get; set;}
public BrambiShop.UI.Pages.Shared._SideCategoriesMenuModel SideMenuModel{ get; set;}
public async Task OnGet()
{
}
}
}
And then use it in your index view
#page
#model IndexModel
#{
ViewData["Title"] = "Home page";
}
#{ await Html.RenderPartialAsync("_SideCategoriesMenu",Model.SideMenuModel); }
The model you use to create the page needs to contain a complete model for the Menu. Then you need to pass the model in the RenderPartial.
IE:
#{ await Html.RenderPartialAsync("_SideCategoriesMenu", Model.SideMenu); }
Edit--
Add the SideMenu property to your Model so you can access it on the page in the above example.
using BrambiShop.API.Models;
using BrambiShop.UI.Services;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace BrambiShop.UI.Pages
{
public class IndexModel : PageModel
{
public IndexModel()
{
}
public SideMenuModel SideMenu { get; set;}
public async Task OnGet()
{
}
}
}

MVC6 alternative to #Html.DisplayFor

MVC6 introduces Tag Helpers which is a better way compared to using #Html.EditorFor, etc. However I have not found any Tag Helper that would be an alternative to #Html.DisplayFor.
Of course I can use a variable directly on a Razor page, such as #Model.BookingCode. But this does not allow to control formatting.
With MVC6, what's conceptually correct way for displaying a value of a model property?
#Html.DisplayFor still exists and can still be used.
The difference between HtmlHelpers and TagHelpers is that HtmlHelpers choose which html elements to render for you whereas TagHelpers work with html tags that you add yourself so you have more full control over what html element is used. You do have some control over the markup using templates with HtmlHelpers but you have more control with TagHelpers.
So you should think in terms of what html markup do I want to wrap this model property in and add that markup around the property itself using #Model.Property with some markup around it or continue using DisplayFor if you prefer to let the helper decide.
You can create your own tag helper
namespace MyDemo.TagHelpers
{
[HtmlTargetElement("p", Attributes = ForAttributeName)]
public class DisplayForTagHelper : TagHelper
{
private const string ForAttributeName = "asp-for";
[HtmlAttributeName(ForAttributeName)]
public ModelExpression For { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (output == null)
{
throw new ArgumentNullException(nameof(output));
}
var text = For.ModelExplorer.GetSimpleDisplayText();
output.Content.SetContent(text);
}
}
}
Add use it in view:
<p asp-for="MyProperty" class="form-control-static"></p>
I have been using this as a display tag helper.
[HtmlTargetElement("*", Attributes = ForAttributeName)]
public class DisplayForTagHelper : TagHelper
{
private const string ForAttributeName = "asp-display-for";
private readonly IHtmlHelper _html;
public DisplayForTagHelper(IHtmlHelper html)
{
_html = html;
}
[HtmlAttributeName(ForAttributeName)]
public ModelExpression Expression { get; set; }
public IHtmlHelper Html
{
get
{
(_html as IViewContextAware)?.Contextualize(ViewContext);
return _html;
}
}
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
if (output == null)
throw new ArgumentNullException(nameof(output));
var type = Expression.Metadata.UnderlyingOrModelType;
if (type.IsPrimitive)
{
output.Content.SetContent(Expression.ModelExplorer.GetSimpleDisplayText());
}
// Special Case for Personal Use
else if (typeof(Dictionary<string, string>).IsAssignableFrom(type))
{
output.Content.SetHtmlContent(Html?.Partial("Dictionary", Expression.ModelExplorer.Model));
}
else
{
var htmlContent = Html.GetHtmlContent(Expression);
output.Content.SetHtmlContent(htmlContent);
}
}
}
public static class ModelExpressionExtensions
{
public static IHtmlContent GetHtmlContent(this IHtmlHelper html, ModelExpression expression)
{
var ViewEngine = html.ViewContext.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
var BufferScope = html.GetFieldValue<IViewBufferScope>();
var htmlContent = new TemplateBuilder(ViewEngine, BufferScope, html.ViewContext, html.ViewContext.ViewData, expression.ModelExplorer, expression.Name, null, true, null).Build();
return htmlContent;
}
public static TValue GetFieldValue<TValue>(this object instance)
{
var type = instance.GetType();
var field = type.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).FirstOrDefault(e => typeof(TValue).IsAssignableFrom(e.FieldType));
return (TValue)field?.GetValue(instance);
}
}
try below code
public class movie
{
public int ID { get; set; }
[DisplayName("Movie Title")]
public string Title { get; set; }
}
///////////////////////////////////////////////////
#model IEnumerable<MvcMovie.Models.Movie>
<h1>Show List Movies</h1>
<label asp-for="ToList()[0].Title">< /label>
#foreach (var movie in Model)
{
#movie.Title
}

MVC 4 HTML is never decoded on POST

I am using a Kendo editor to create email templates and on POST, once a change to the template has been submitted, always renders in encoded HTML.
This is my razor code on the page:
#model Business.Models.Administration.EmailSetupViewModel
#using Kendo.Mvc.UI;
<h2>Application Stages Portal</h2>
<h4>Email Setup</h4>
#using (Html.BeginForm())
{
if (Model.EmailSaved)
{
<h2>
Email template saved</h2>
}
else
{
#* #Html.DisplayFor(m => m.EmailSavedMsg)*#
}
#Html.DropDownListFor(m => m.EmailTemplateToEdit, Model.EmailTemplatesList)
<input type="submit" name="setup" value="setup" />
if (Model.ShowEmailForm)
{
<div id="email-edit">
#Html.Label("Title")
#Html.TextBoxFor(m => m.EmailTitle, new { style = "width:200px" })
<br />
#(Html.Kendo().Editor()
.Name("editor")
.HtmlAttributes(new { style = "width: 600px;height:440px" })
.Value(#<text>
#Html.Raw(Model.EmailBody)
</text>))
</div>
<input type="submit" id="btnSaveTemplate" name="update" value="update" />
<h2>
Please note</h2>
<p>
The following items are <i>reserved and should not be changed, you may move them
to a different place within the message. </i>
<ul>
<li><*name*> e.g. Fred Flinstone </li>
<li><*membernumber*> e.g. 12345678 </li>
</ul>
</p>
}
}
And this is where the actual editor markup is on the page
#(Html.Kendo().Editor()
.Name("editor")
.HtmlAttributes(new { style = "width: 600px;height:440px" })
.Value(#<text>
#Html.Raw(Model.EmailBody)
</text>))
Model.EmailBody contains the actual string.
When I GET the page, it renders fine. But when I do POST it never decodes so the rendering is wrong. I don't want to see all the HTML tags but the actual formatting.
This is my Controller code:
#region Email template
[HttpGet]
public ActionResult EmailSetup()
{
ViewBag.DisplayName = StaticFunctions.GetDisplayName(this.User.Identity.Name);
EmailSetupViewModel model = new EmailSetupViewModel();
Business.Administration.Email Email = new Business.Administration.Email();
var list = Email.GetTemplateList();
model.EmailTemplatesList = list.OrderBy(o => o.Text).ToList();
return View(model);
}
[HttpPost]
public ActionResult EmailSetup(EmailSetupViewModel model, string value, string editor)
{
ViewBag.DisplayName = StaticFunctions.GetDisplayName(this.User.Identity.Name);
string body = HttpUtility.HtmlDecode(editor); //encode to db
if (Request["update"] != null)
{
Business.Administration.Email Email = new Business.Administration.Email();
model.EmailSaved = Email.SaveTemplate(model, body);
//ModelState.Clear(); // when doing POST - clearing the ModelState will prevent encode of HTML (Default behaviour). This isn't good long term solution.
if (model.EmailSaved)
{
model.EmailSavedMsg = "Template saved";
}
else
{
model.EmailSavedMsg = "Template couldn't be saved";
}
model.EmailTemplatesList = Email.GetTemplateList();
model = Email.GetTemplate(model);
model.EmailBody = HttpUtility.HtmlDecode(model.EmailBody);
return View(model);
}
else
{
Business.Administration.Email Email = new Business.Administration.Email();
model.EmailTemplatesList = Email.GetTemplateList();
model = Email.GetTemplate(model);
model.EmailBody = HttpUtility.HtmlDecode(model.EmailBody);
return View(model);
}
}
#endregion
This is my model, I am using [AllowHtml] attribute on the property.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
namespace Business.Models.Administration
{
public class EmailSetupViewModel
{
public EmailSetupViewModel()
{
this.EmailTemplatesList = new List<SelectListItem>();
}
public string EmailTemplateToEdit { get; set; }
public List<SelectListItem> EmailTemplatesList { get; set; }
public string EmailTitle { get; set; }
[AllowHtml]
public string EmailBody { get; set; }
public bool ShowEmailForm { get; set; }
public bool EmailSaved { get; set; }
public string EmailSavedMsg { get; set; }
}
}
Finally two screenshots, one on GET and one on POST.
I was using ModelState.Clear() as well but when I clicked back on the browser, it wouldn't decode.
So basically I want help rendering the HTML in my editor on post so it renders properly and doesn't show HTML tags in the editor.