Sunday 30 August 2020

HOW TO SAVE & DISPLAY HTML CONTENT IN ASP.NET MVC5

In web development, sometimes, it becomes necessary to write and save content in HTML format. In order to write HTML content many jquery base rich text editor plugins are available out there which are easily integrated with ASP.NET MVC5. Saving and displaying the HTML content is entirely different topic and it is completely platform dependent that what sort of options or libraries do the platform provides in order to save and display the HTML content


 Let's begin now.


1) First create your SQL server database and name it "db_html". Then execute following script into your SQL server database i.e.

USE [db_html]
GO
/****** Object:  StoredProcedure [dbo].[Insert_HTML_Content]    Script Date: 2/20/2019 4:47:28 PM ******/
DROP PROCEDURE [dbo].[Insert_HTML_Content]
GO
/****** Object:  StoredProcedure [dbo].[display_all_HTML_Content]    Script Date: 2/20/2019 4:47:28 PM ******/
DROP PROCEDURE [dbo].[display_all_HTML_Content]
GO
/****** Object:  Table [dbo].[tbl_html_info]    Script Date: 2/20/2019 4:47:28 PM ******/
DROP TABLE [dbo].[tbl_html_info]
GO
/****** Object:  Table [dbo].[tbl_html_info]    Script Date: 2/20/2019 4:47:28 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl_html_info](
 [id] [int] IDENTITY(1,1) NOT NULL,
 [html_content] [nvarchar](max) NOT NULL,
 CONSTRAINT [PK_tbl_html_info] PRIMARY KEY CLUSTERED 
(
 [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO
/****** Object:  StoredProcedure [dbo].[display_all_HTML_Content]    Script Date: 2/20/2019 4:47:28 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:  <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE [dbo].[display_all_HTML_Content]
AS
BEGIN
 SELECT [id]
    ,[html_content]
 FROM [dbo].[tbl_html_info]
END

GO
/****** Object:  StoredProcedure [dbo].[Insert_HTML_Content]    Script Date: 2/20/2019 4:47:28 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:  <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE [dbo].[Insert_HTML_Content] 
 @html_content NVARCHAR(MAX)
AS
BEGIN
 INSERT INTO [dbo].[tbl_html_info]
      ([html_content])
 VALUES
      (@html_content)
END

GO

Don't forget to update your database connection in "Web.Config" file.

2) Create a new MVC web project and name it "MVCDisplayHTMLContent".  

3) Open the "Views->Shared->_Layout.cshtml" file and replace following code in it i.e.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

    <!-- Font Awesome -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" />

</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <center>
                <p><strong>Copyright &copy; @DateTime.Now.Year - <a href="http://www.asmak9.com/">Asma's Blog</a>.</strong> All rights reserved.</p>
            </center>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")

    @RenderSection("scripts", required: false)
</body>
</html>

In the above code, I have simply created a basic default layout page and linked the require libraries into it.

4) Now, create a new "Models\HTMLDisplayViewModel.cs" file and replace the following code in it i.e.

//-----------------------------------------------------------------------
// <copyright file="HTMLDisplayViewModel.cs" company="None">
//     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose.
// </copyright>
// <author>Asma Khalid</author>
//-----------------------------------------------------------------------

namespace MVCDisplayHTMLContent.Models
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;

    /// <summary>
    /// HTML display view model class.
    /// </summary>
    public class HTMLDisplayViewModel
    {
        /// <summary>
        /// Gets or sets the HTML content property.
        /// </summary>
        [AllowHtml]
        [Required]
        [Display(Name = "HTML Content")]
        public string HtmlContent { get; set; }

        /// <summary>
        /// Gets or sets message property.
        /// </summary>
        [Display(Name = "Message")]
        public string Message { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether it is valid or not property.
        /// </summary>
        [Display(Name = "Is Valid")]
        public bool IsValid { get; set; }

        /// <summary>
        /// Gets or sets list property.
        /// </summary>
        public List<display_all_HTML_Content_Result> HTMLContentList { get; set; }
    }
}

In the above code, I have created my view model which I will attach with my view. Here, I have created string type HTML content property and attach [AllowHtml] data annotation to allow HTML content to be captured from the end-user. I have also added message property which will display either success or failure messages from server side. Then I have added is valid property which will validate success or failure from server side to display proper message and finally, I have added HTML content list property which will display the list of all saved HTML content from the database.

5) Create a new "Controllers\HTMLDisplayController.cs" file and replace the following code in it i.e.

//-----------------------------------------------------------------------
// <copyright file="HTMLDisplayController.cs" company="None">
//     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose.
// </copyright>
// <author>Asma Khalid</author>
//-----------------------------------------------------------------------

namespace MVCDisplayHTMLContent.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Models;

    /// <summary>
    /// HTML display controller class.
    /// </summary>
    public class HTMLDisplayController : Controller
    {
        #region Private Property

        /// <summary>
        /// Gets or sets database manager property.
        /// </summary>
        private db_htmlEntities databaseManager = new db_htmlEntities();

        #endregion

        #region Index view method.

        #region Get: /HTMLDisplay/Index method.

        /// <summary>
        /// Get: /HTMLDisplay/Index method.
        /// </summary>        
        /// <returns>Return index view</returns>
        public ActionResult Index()
        {
            // Initialization/
            HTMLDisplayViewModel model = new HTMLDisplayViewModel() { HtmlContent = null, IsValid = false, Message = string.Empty, HTMLContentList = new List<display_all_HTML_Content_Result>() };

            try
            {
                // Get info list.
                model.HTMLContentList = this.databaseManager.display_all_HTML_Content().ToList();
            }
            catch (Exception ex)
            {
                // Info
                Console.Write(ex);
            }

            // Info.
            return this.View(model);
        }

        #endregion

        #region POST: /HTMLDisplay/Index

        /// <summary>
        /// POST: /HTMLDisplay/Index
        /// </summary>
        /// <param name="model">Model parameter</param>
        /// <returns>Return - Response information</returns>
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Index(HTMLDisplayViewModel model)
        {
            try
            {
                // Verification
                if (ModelState.IsValid)
                {
                    // save info.
                    this.databaseManager.Insert_HTML_Content(model.HtmlContent);

                    // Commit database.
                    this.databaseManager.SaveChanges();

                    // Settings.
                    model.HTMLContentList = this.databaseManager.display_all_HTML_Content().ToList();
                    model.Message = "Information successfully!! saved.";
                    model.IsValid = true;
                }
                else
                {
                    if (string.IsNullOrEmpty(model.HtmlContent))
                    {
                        // Settings.
                        model.HTMLContentList = new List<display_all_HTML_Content_Result>();
                        model.Message = "Require field can not be emptied";
                        model.IsValid = false;
                    }
                }
            }
            catch (Exception ex)
            {
                // Info
                Console.Write(ex);
            }

            // Info
            return this.View(model);
        }

        #endregion

        #endregion
    }
}

In the above code, I have created  databaseManager private property which will allow me to access my SQL database via entity framework. Then, I have created GET "Index(...)" method which will retrieve list of HTML content data from SQL database and send it to the view page. Finally, I have created POST "Index(...)" method which will receive input HTML content from the end-user, save the HTML content into the SQL database and finally I have retrieved the saved HTML content list and pass that list to the view page.

6) Now, create a view "Views\HTMLDisplay\Index.cshtml" file and replace the following code in it i.e.

@using MVCDisplayHTMLContent.Models
@model HTMLDisplayViewModel
@{
    ViewBag.Title = "ASP.NET MVC5: Save and Display HTML content.";
}

<div class="row">
    <div class="panel-heading">
        <div class="col-md-8">
            <h3>
                <i class="fa fa-file-text-o"></i>
                <span>ASP.NET MVC5: Save and Display HTML content</span>
            </h3>
        </div>
    </div>
</div>

<br />

<div class="row">
    <div class="col-md-12">
        <section>
            @using (Html.BeginForm("Index", "HTMLDisplay", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
            {
                @Html.AntiForgeryToken()

                <h5>
                    <i class="fa fa-link" aria-hidden="true"></i>
                    <a href="http://summernote.org/">Summernote Rich Text WYSIWYG Editor</a>
                </h5>

                <hr />

                <div class="form-group">
                    <label class="col-md-4 control-label">HTML Contnet </label>
                    <div class="col-md-8">
                        <div class="input-group">
                            @Html.TextAreaFor(m => m.HtmlContent, new { rows = "20", style = "resize:none;width:400px;", placeholder = Html.DisplayNameFor(m => m.HtmlContent), @class = "form-control input-lg textarea-editor" })
                        </div>
                            @if (Model.IsValid && !string.IsNullOrEmpty(Model.Message))
                            {
                                <span class="text-success">@Model.Message</span>
                            }
                            else
                            {
                                <span class="text-danger">@Model.Message</span>
                                @Html.ValidationMessageFor(m => m.HtmlContent, "", new { @class = "text-danger" })
                            }
                    </div>
                </div>

                <div class="form-group">
                        <div class="col-md-10 col-md-push-4">
                            <input type="submit" value="Save" class="btn btn-info" />
                        </div>
                    </div>
            }
        </section>
    </div>
</div>

<hr />

@if (Model.HTMLContentList != null &&
                 Model.HTMLContentList.Count > 0)
{
    <div class="row">
        <div class="col-md-offset-4 col-md-8">
            <h3>List of HTML Content </h3>
        </div>
    </div>

    <hr />

    <div class="row">
        <div class="col-md-offset-1 col-md-8">
            <section>
                <table class="table table-bordered table-striped">
                    <thead>
                        <tr>
                            <th style="text-align: center;">Sr.</th>
                            <th style="text-align: center;">HTML Content</th>
                        </tr>
                    </thead>

                    <tbody>
                        @for (int i = 0; i < Model.HTMLContentList.Count; i++)
                        {
                            <tr>
                                <td style="text-align: center;">@(i + 1)</td>

                                <td style="text-align: center;">
                                    <div class="input-group">
                                        @Html.Raw(Model.HTMLContentList[i].html_content)
                                    </div>
                                </td>
                            </tr>
                        }
                    </tbody>
                </table>
            </section>
        </div>
    </div>
}

@section Scripts
{
    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.2/summernote.js"></script>
    @Scripts.Render("~/bundles/Script-custom-editor")

    <link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.2/summernote.css" rel="stylesheet">

}

In the above code, I have created a simple view for taking HTML content input from the end-user via Rich Text Editor, then, I have displayed the list of HTML content that is being saved by the user on my server into SQL database.

In the list part of the above code, following line of code will display the HTML content on the view page i.e.

@Html.Raw(Model.HTMLContentList[i].html_content)

The above line of code take string or object type value as input and then display the content in HTML format.

7) Now, execute the project and you will be able to see the following in action i.e.