Wednesday, September 17, 2014

CK Editor implement your own Image upload ASP.net MVC

We see that many of WYSIWYG have implementation of image upload but when you actually want to implement that most them don't provide image upload upload right away. However with CK Editor I found a way to implement the image upload using ASP.net. However the coding is very simple so you can implement the same in PHP and other languages also.

First create a project (here I have named it ckeditorfortest). Select default options as given in the images below.




Now visit site http://ckeditor.com/download and download the standard version as shown in the picture.



After you have downloaded, upzip the package and include in the root of the project like this



Include the same in the Layout page.

Now to start with, in the index page remove all data and simply post the following lines of code

<textarea id="editor1" name="editor1">&lt;p&gt;Initial value.&lt;/p&gt;</textarea>

This is only put a Text Area in the page with id="editor1" and name="editor1". Please ensure that your textarea has id and name, without these attributes CK editor will not work.

Now after doing this put the following code in the Index.cshtml page

<script type="text/javascript">
    CKEDITOR.replace('editor1');
</script>

This will not enable the editor and when you run the program you will see page like this


You will see that the WYSIWYG is enabled for the textbox and is working. Now click on the image linkand then you will see the following modal dialog come up.


As you can see we don't have option to upload images in this, but you can still provide image URL to include. Now to enable image browsing modify the script we wrote previously in the Index.cshtml to the following:

<script type="text/javascript">
    CKEDITOR.replace('editor1', {
        filebrowserImageBrowseUrl: '/home/uploadPartial',
        filebrowserImageUploadUrl: '/home/uploadnow'
    });
</script>

Now after implementing this code, reload the /home/Index page and click on the image icon in the editor toolbar again. What this code basically does is it gives CK editor what is the url where we are going to implement the Image browser and what is the url where we are going to implement the upload functionality.



Now you can see that we have one new tab call "Upload" and in "Image Info" tab also a new button has come up which says "Browse Server". In the "Upload" tab you will see option to choose file and send it to server. If you click the same now it will not work nor will the "Browse Server" button in "Image Info" tab.



Now let's build the functionality for these tabs.
First let's create a viewmodel for holding the imageurl(the image url contains the image name also). So right click on the model folder and create class file and name the class file imagesviewmodel.cs. Paste the following code in the viewmodel.



public class imagesviewmodel
{
    public string Url { get; set; }
}

Next, open the home controller and paste the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ckeditortest.Models;
using System.IO;

namespace ckeditortest.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
        public void uploadnow(HttpPostedFileWrapper upload)
        {
            if(upload!=null)
            {
                string ImageName = upload.FileName;
                string path = System.IO.Path.Combine(Server.MapPath("~/Images/uploads"), ImageName);
                upload.SaveAs(path);
            }
        }
    }
}

Here apart from the Index action we have added one other action methods. Please ensure to add using System.IO;
In this new action method which if you realize is same as given in previous jquery script we wrote in Index.cshtml "filebrowserImageUploadUrl: '/home/uploadnow'", we need to ensure that the name of the action method remains the same. This action will take in a HttpPostedFileWrapper input which we have named upload. The filewrapper will have following information



but we here will be using FileName only. So we will first check if the upload HttpPostedFileWrapper is properly loaded, once that is ascertained we will generate the string path by combining the path where image will be uploaded in the server with the filename. upload.SaveAs(path) will save the image to the local provided. Also ensure that the action returns void because we don't need to do any action after upload and the page should remain as it is. Now if you try to run the program and go to "Upload" tab and click choose file you can choose file and click on "send it to server" and same will be uploaded to the server.
Now the upload is complete. Now we will look at how we will insert this image into the WYSIWYG editor.
For that we will create another action in the home controller as given in the jquery in the Index.cshtml "filebrowserImageBrowseUrl: '/home/uploadPartial',"the following code lists the action method.

public ActionResult uploadPartial()
{
     var appData = Server.MapPath("~/Images/uploads");
     var images = Directory.GetFiles(appData).Select(x => new imagesviewmodel
     {
        Url = Url.Content("/images/uploads/" + Path.GetFileName(x))
     });
     return View(images);
}

this action method will basically list out all images that are there in the upload directory for the user to choose which image he wants to insert into the WYSIWYG. So the variable "images" take all images that are there in the upload directory along with filename and path. The action method sends this variable to the view.
Next right click on the action method and create view and name the view uploadPartial.cshtml.
Paste the following code in the view.

@model IEnumerable<ckeditortest.Models.imagesviewmodel>

@foreach (var image in Model)
{
    <a href="#" class="returnImage" data-url="@Request.Url.GetLeftPart(UriPartial.Authority)@image.Url">
        <img src="@image.Url" alt="Hejsan" id="#image" data-source="@image.Url" width="200" height="200"/>
    </a>
}
<script type="text/javascript">
    $(document).ready(function () {
        $(".returnImage").click("click", function (e) {
            var urlImage = $(this).attr("data-url");
            window.opener.updateValue("cke_72_textInput", urlImage);
            window.close();
        });
    });
</script>

So upon completing this if you click on the "Browse Server" button, a new page will open which will show all the images in the upload folder. As shown below:



To understand what is done in the view, we make this view strongly typed to the viewmodel we create earlier. Now we run through each of the image and append the same to an html anchor. As your will notice we will put in the full path of the image file in data-source attribute. Here @Request.Url.GetLeftPart(UriPartial.Authority) will give the left part of the url of your website. That is if your website url is http://localhost:5938 then this will be returned even if you are http://localhost:5938/home/uploadpartial location. To this we will append the image url which is basically location of the image from the root folder along with image name. So this makes the image clickable. Below we will write some jquery to take the image URL which needs to be returned to "Image Info" tab in the modal dialog where we clicked "Browse server". What this jquery code does is basically take the image url and send it the opener page which opened this page. So it will be sent one step back and then we close the window.
As of now if you click on the image nothing will happen. For the image url to come in the "Image Info" tab URL textbox follow the steps below.

Now one final step in the Index.cshtml add one function to get the value of image url from uploadpartial and put that value in the URL textbox in "Image Info" tab. I will give you the full script section so that we don't get confused.

<script type="text/javascript">
    CKEDITOR.replace('editor1', {
        filebrowserImageBrowseUrl: '/home/uploadPartial',
        filebrowserImageUploadUrl: '/home/uploadnow'
    });

    function updateValue(id, value) {
        // this gets called from the popup window and updates the field with a new value 
        document.getElementById(id).value = value;
    }
</script>

The function updateValue basically takes the id of the element in this case the URL textbox which we send from uploadpartial and the value and inputs the value to the textbox.

Now recompile the code and run now if you go to "Image Info" tab, and click "Browse Server" button you will be shown the uploadpartial, which will basically show all images (clickable) from the upload folder. When you click on any of the image the uploadpartial will be closed and the url of the clicked image will be populated in "URL" textbox of the "Image Info" tab. If you click "Ok" now you will see that the image is inserted in the WYSIWYG editor like in the image below:



Full Code:
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ckeditortest.Models;
using System.IO;

namespace ckeditortest.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

            return View();
        }
        public ActionResult uploadPartial()
        {
            var appData = Server.MapPath("~/Images/uploads");
            var images = Directory.GetFiles(appData).Select(x => new imagesviewmodel
            {
                Url = Url.Content("/images/uploads/" + Path.GetFileName(x))
            });
            return View(images);
        }
        public void uploadnow(HttpPostedFileWrapper upload)
        {
            if(upload!=null)
            {
                string ImageName = upload.FileName;
                string path = System.IO.Path.Combine(Server.MapPath("~/Images/uploads"), ImageName);
                upload.SaveAs(path);
            }

        }
    }
}

imagesviewmodel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ckeditortest.Models
{
    public class imagesviewmodel
    {
        public string Url { get; set; }
    }
}

Index.cshtml
@{
    ViewBag.Title = "Home Page";
}

<textarea id="editor1" name="editor1">&lt;p&gt;Initial value.&lt;/p&gt;</textarea>
<script type="text/javascript">
    CKEDITOR.replace('editor1', {
        filebrowserImageBrowseUrl: '/home/uploadPartial',
        filebrowserImageUploadUrl: '/home/uploadnow'
    });

    function updateValue(id, value) {
        // this gets called from the popup window and updates the field with a new value 
        document.getElementById(id).value = value;
    }
</script>

uploadPartial.cshtml
@model IEnumerable<ckeditortest.Models.imagesviewmodel>

@foreach (var image in Model)
{
    <a href="#" class="returnImage" data-url="@Request.Url.GetLeftPart(UriPartial.Authority)@image.Url">
        <img src="@image.Url" alt="Hejsan" id="#image" data-source="@image.Url" width="200" height="200"/>
    </a>
}
<script type="text/javascript">
    $(document).ready(function () {
        $(".returnImage").click("click", function (e) {
            var urlImage = $(this).attr("data-url");
            //This takes the data value and id of the editor and sends the data(i.e.,image url) back to the caller page
            window.opener.updateValue("cke_72_textInput", urlImage);
            window.close();
        });
    });
</script>

_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title - My ASP.NET MVC Application</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
        <script type="text/javascript" src="http://localhost:50972/ckeditor/ckeditor.js"></script>
        <script src="~/Scripts/jquery-1.8.2.js"></script>
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    </head>
    <body>
        <header>
            <div class="content-wrapper">
                <div class="float-left">
                    <p class="site-title">@Html.ActionLink("your logo here", "Index", "Home")</p>
                </div>
                <div class="float-right">
                    <section id="login">
                        @Html.Partial("_LoginPartial")
                    </section>
                    <nav>
                        <ul id="menu">
                            <li>@Html.ActionLink("Home", "Index", "Home")</li>
                            <li>@Html.ActionLink("About", "About", "Home")</li>
                            <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                        </ul>
                    </nav>
                </div>
            </div>
        </header>
        <div id="body">
            @RenderSection("featured", required: false)
            <section class="content-wrapper main-content clear-fix">
                @RenderBody()
            </section>
        </div>
        <footer>
            <div class="content-wrapper">
                <div class="float-left">
                    <p>&copy; @DateTime.Now.Year - My ASP.NET MVC Application</p>
                </div>
            </div>
        </footer>

        @Scripts.Render("~/bundles/jquery")
        @RenderSection("scripts", required: false)
    </body>
</html>


Enjoy free image upload capability in CK editor.

Sunday, May 18, 2014

Export to Excel, Send Email and Captcha Implementation in ASP.NET MVC

Create a project, name it "ExportToExcelSendEmailandRecaptcha"

After you add the project Select "MVC" project and click "Ok"

You will see the following solution is added
Add a ViewModel Folder and right click and add class. As class as "Instructor.cs"

After this define the model, please remember for this demo the model is not important so I am not going to database and creating the model. I will only be using this viewModel as my model.
Add the following code in "Instructor.cs"

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ExportToExcelSendEmailandRecaptcha.ViewModel
{
   public class Instructor
   {
     public string FirstName { get; set; }
     public string LastName { get; set; }
     public string Email { get; set; }
     public string Mobile { get; set; }
   }
}


Now that we have created the class for model, let's go to HomeController.cs and make the following changes to display our index page as it would come from the database. Add the following code in index action method.

public ActionResult Index()
{

    var instructors = new List<Instructor>
    {
     new Instructor{FirstName="Carson", LastName = "Alexander", Email="carson.alexander@xyz.com", Mobile="8888888888"},
     new Instructor{FirstName="Meredith", LastName = "Alonso", Email="carson.alexander@xyz.com", Mobile="8888888888"},
     new Instructor{FirstName="Arturo", LastName = "Anand", Email="carson.alexander@xyz.com", Mobile="8888888888"},
    new Instructor{FirstName="Gytis", LastName = "Barzdukas", Email="carson.alexander@xyz.com", Mobile="8888888888"},
   new Instructor{FirstName="Yan", LastName = "Li", Email="carson.alexander@xyz.com", Mobile="8888888888"},
   new Instructor{FirstName="Peggy", LastName = "Justice", Email="carson.alexander@xyz.com", Mobile="8888888888"},
   new Instructor{FirstName="Laura", LastName = "Norman", Email="carson.alexander@xyz.com", Mobile="8888888888"},
   new Instructor{FirstName="Nino", LastName = "Olivetto", Email="carson.alexander@xyz.com", Mobile="8888888888"}
    };
   TempData["instructors"] = instructors;
   return View(instructors);
}

This should give us the normal kind of view whenever we open an index view, but for that you need to right click on the action and click view. Let's make the view linked to the viewmodel we had created for making it easy to implement.




Now click run and this is the page you should see


Now add the Export to excel button to the view, write the following code in the view:


Now your view should look like this.


Now let's implement the export to excel button. In the controller add the following code.
In the action definition add


Now add the reuse object with the following code, please also note the reference added

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ExportToExcelSendEmailandRecaptcha.ViewModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;

namespace ExportToExcelSendEmailandRecaptcha.Reuse
{
    public class Reuse
    {
        internal void actualExport(List<Instructor> instructors, HttpResponseBase resp)
        {
            GridView gv = new GridView();
            gv.DataSource = instructors;
            gv.DataBind();
            resp.ClearContent();
            resp.Buffer = true;
            resp.AddHeader("content-disposition", "attachment; filename=" + "instructor" + ".xls");
            resp.ContentType = "application/msexcel";
            resp.Charset = "";
            StringWriter sw = new StringWriter();
            HtmlTextWriter htw = new HtmlTextWriter(sw);
            gv.RenderControl(htw);
            resp.Output.Write(sw.ToString());
            resp.Flush();
            resp.End();
        }
    }
}



Now you are ready, click on the button and you should be asked to save the excel sheet.


You can save the excel sheet and you will see that you have the same table as in index


Now let's move to the other section for sending Email using hotmail (Now Outlook) using your code. The idea is the administrator will get email when comment will be updated by anyone in the website.

First in the Reuse.cs add the following reference

using System.Net;
using System.Net.Mail;

//Then add this code below the actualExport function:


internal bool sendEmail(string strReceiver, string strSubject, string strComment)
{
       try
       {
                MailMessage mailMessage = new MailMessage();
                mailMessage.From = new MailAddress("defAdminEmail@hotmail.com", "anyAlias");
                mailMessage.To.Add(strReceiver);
                mailMessage.Subject = strSubject;
                mailMessage.Body = strComment;
                mailMessage.IsBodyHtml = true;

                SmtpClient smtpClient = new SmtpClient();
                smtpClient.Host = "smtp-mail.outlook.com";
                smtpClient.Port = 587;
                smtpClient.EnableSsl = true;

                NetworkCredential networkCredential = new NetworkCredential();
                networkCredential.UserName = "abc@hotmail.com";
                networkCredential.Password = "abcde";
                smtpClient.UseDefaultCredentials = true;
                smtpClient.Credentials = networkCredential;

                smtpClient.Send(mailMessage);
                return true;
         }
         catch (Exception e)
         {
                return false;
          }
 }




anyAlias highlighted in orange is the display name with which the email will be sent. Now in the HomeController add the contact function

public ActionResult Contact()
{
    ViewBag.Message = TempData["submitMessage"];
    return View();
}

Now create another ViewModel as follows and name it ContactWithEmail.cs. I am creating this ViewModel even for one single component in the page to show that we can have components exported in email and also to make it easier for Captcha implementation, which I will talk about later.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace ContosoUniversity.ViewModels
{
    public class ContactWithEmail
    {
        [Required(ErrorMessage = "Please enter Comment")]
        public string Comment { get; set; }
    }
}

now build the code to add strongly typed view with the ViewModel. Select the following options:


With this an edit form will be generate called Contact.cshtml. In the generated code you will see @Html.EditorFor. Please change that to @Html.TextAreaFor. The code will look like the following now

@model ExportToExcelSendEmailandRecaptcha.ViewModel.ContactWithEmail
@{
    ViewBag.Title = "Contact";
}

<h2>Contact</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>ContactWithEmail</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @ViewBag.Message
        <div class="form-group">
        @Html.LabelFor(model => model.Comment, htmlAttributes: new { @class = "control-label col-md-2" })
        @Html.TextAreaFor(model => model.Comment, new { htmlAttributes = new { @class = "form-control" }, rows="5", cols="50" })
        @Html.ValidationMessageFor(model => model.Comment, "", new { @class = "text-danger" })
    </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>

}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Now let's create the post action for contact with the following code

[HttpPost]
public ActionResult Contact(ContactWithEmail contact)
{
     if (ModelState.IsValid)
      {
           if (ReUse.sendEmail("abc@hotmail.com", "From Website", contact.Comment))
           {
               TempData["submitMessage"] = "You have successfully submitted your message, you will be contacted shortly";
               return RedirectToAction("contact");
           }
           else
           {
               TempData["submitMessage"] = "Sorry currently your email couldn't be sent";
                return RedirectToAction("contact");
            }
        }
       return View(contact);
}

Please try to put a comment and send message now to see it will work :)

Now let's move to captcha implementation, we don't want bots saving comments do we. For this we need to go to NuGet and get ReCaptcha plugin. Open NuGet and search for ReCaptcha as below:


Click on install and follow through. Now add the following to the reference in HomeController.cs

using Recaptcha.Web;
using Recaptcha.Web.Mvc;
using System.Threading.Tasks;

Then make the following changes to the Web.config file that is on the outermost solution

<appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="recaptchaPublicKey" value="6LcYP-YSAAAAAG4Pir8LWAtarfN7ZfEaGgJ9H7Gv" />
    <add key="recaptchaPrivateKey" value="6LcYP-YSAAAAAHq5pXcy5_PB7nY-AB-P-4hVG9rO" />
</appSettings>

In the contact.cshtml make the following changes (highlighted in yellow)

@model ExportToExcelSendEmailandRecaptcha.ViewModel.ContactWithEmail
@using Recaptcha.Web.Mvc;
@{
    ViewBag.Title = "Contact";
}

<h2>Contact</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>ContactWithEmail</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @ViewBag.Message
        <div class="form-group">
        @Html.LabelFor(model => model.Comment, htmlAttributes: new { @class = "control-label col-md-2" })
        @Html.TextAreaFor(model => model.Comment, new { htmlAttributes = new { @class = "form-control" }, rows="5", cols="50" })
        @Html.ValidationMessageFor(model => model.Comment, "", new { @class = "text-danger" })
    </div>
        <div class="form-group">
            @Html.Label("   ", new { @class = "col-sm-2 control-label" })
            @Html.Recaptcha(theme: Recaptcha.Web.RecaptchaTheme.Clean)
        </div>
        <div class="form-group">
           <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}



<div>

    @Html.ActionLink("Back to List", "Index")

</div>

Your contact.cshtml should now look like this


Now let's implement the final code for checking the captcha. This will change the post action method for contact in the HomeController.cs

[HttpPost]
public async Task<ActionResult> Contact(ContactWithEmail contact)
{
     RecaptchaVerificationHelper recaptchaHelper = this.GetRecaptchaVerificationHelper();

     if (string.IsNullOrEmpty(recaptchaHelper.Response))
     {
         ModelState.AddModelError("", "Captcha answer cannot be empty");
         return View(contact);
     }
     RecaptchaVerificationResult recaptchaResult = await recaptchaHelper.VerifyRecaptchaResponseTaskAsync();
     if (recaptchaResult != RecaptchaVerificationResult.Success)
    {
        ModelState.AddModelError("", "Incorrect captcha error");
    }


    if (ModelState.IsValid)
    {
        if (ReUse.sendEmail("abc@hotmail.com", "From Website", contact.Comment))
        {
           TempData["submitMessage"] = "You have successfully submitted your message, you will be contacted shortly";
            return RedirectToAction("contact");
        }
        else
       {
            TempData["submitMessage"] = "Sorry currently your email couldn't be sent";
            return RedirectToAction("contact");
        }
    }
    return View(contact);
}

This is the final implementation. I couldn't find a way to upload my code, if you need, please contact me I will be happy to share. However, I have also pasted all my code below, please don't forget to add NuGet reference for recaptcha.

Final Codes:
HomeController.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ExportToExcelSendEmailandRecaptcha.ViewModel;
using System.Collections;
using ExportToExcelSendEmailandRecaptcha.Reuse;
using Recaptcha.Web;
using Recaptcha.Web.Mvc;
using System.Threading.Tasks;

namespace ExportToExcelSendEmailandRecaptcha.Controllers
{
    public class HomeController : Controller
    {
        Reuse.Reuse ReUse = new Reuse.Reuse();

        public ActionResult Index(bool? toExport=false)
        {
            var instructors = new List<Instructor>
            {
                new Instructor{FirstName="Carson", LastName = "Alexander", Email="carson.alexander@xyz.com", Mobile="8888888888"},
                new Instructor{FirstName="Meredith", LastName = "Alonso", Email="carson.alexander@xyz.com", Mobile="8888888888"},
                new Instructor{FirstName="Arturo", LastName = "Anand", Email="carson.alexander@xyz.com", Mobile="8888888888"},
                new Instructor{FirstName="Gytis", LastName = "Barzdukas", Email="carson.alexander@xyz.com", Mobile="8888888888"},
                new Instructor{FirstName="Yan", LastName = "Li", Email="carson.alexander@xyz.com", Mobile="8888888888"},
                new Instructor{FirstName="Peggy", LastName = "Justice", Email="carson.alexander@xyz.com", Mobile="8888888888"},
                new Instructor{FirstName="Laura", LastName = "Norman", Email="carson.alexander@xyz.com", Mobile="8888888888"},
                new Instructor{FirstName="Nino", LastName = "Olivetto", Email="carson.alexander@xyz.com", Mobile="8888888888"}
            };
            
            //Not for first time load, will be triggered only when you click on export to excel
            if (toExport == true)
            {
                ReUse.actualExport(instructors.ToList(),this.Response);
            }
            return View(instructors);
        }

        public ActionResult Contact()
        {
            //For error or success message display when redirected
            ViewBag.Message = TempData["submitMessage"];
            return View();
        }

        [HttpPost]
        public async Task<ActionResult> Contact(ContactWithEmail contact)
        {
            RecaptchaVerificationHelper recaptchaHelper = this.GetRecaptchaVerificationHelper();

            if (string.IsNullOrEmpty(recaptchaHelper.Response))
            {
                ModelState.AddModelError("", "Captcha answer cannot be empty");
                return View(contact);
            }
            RecaptchaVerificationResult recaptchaResult = await recaptchaHelper.VerifyRecaptchaResponseTaskAsync();

            if (recaptchaResult != RecaptchaVerificationResult.Success)
            {
                ModelState.AddModelError("", "Incorrect captcha error");
            }

            if (ModelState.IsValid)
            {
                if (ReUse.sendEmail("abc@hotmail.com", "From Website", contact.Comment))
                {
                    TempData["submitMessage"] = "You have successfully submitted your message, you will be contacted shortly";
                    return RedirectToAction("contact");
                }
                else
                {
                    TempData["submitMessage"] = "Sorry currently your email couldn't be sent";
                    return RedirectToAction("contact");
                }

            }
            return View(contact);
        }
    }
}

Index.cshtml

@model IEnumerable<ExportToExcelSendEmailandRecaptcha.ViewModel.Instructor>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
@using (Html.BeginForm("Index","Home",FormMethod.Get))
{
    @Html.Hidden("toExport",true)
    <input type="submit" class="btn btn-danger" value="Export to Excel" />
}


<p>
    
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.FirstName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.LastName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Email)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Mobile)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.FirstName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.LastName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Email)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Mobile)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
        </td>
    </tr>
}

</table>

Reuse.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ExportToExcelSendEmailandRecaptcha.ViewModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Net;
using System.Net.Mail;

namespace ExportToExcelSendEmailandRecaptcha.Reuse
{
    public class Reuse
    {
        internal void actualExport(List<Instructor> instructors, HttpResponseBase resp)
        {
            //We will use grid to put the same in excel by creating XML which will be saved as excel
            //create new grid handle
            GridView gv = new GridView();
            //assign the instructor table as datasource
            gv.DataSource = instructors;
            //bind the data source with the grid handle
            gv.DataBind();
            resp.ClearContent();
            resp.Buffer = true;
            //This gives the name of the excel sheet, inplace of "instructor" you can have different filename
            //If you want different file name you can have this also sent from the controller
            resp.AddHeader("content-disposition", "attachment; filename=" + "instructor" + ".xls");
            resp.ContentType = "application/msexcel";
            resp.Charset = "";
            StringWriter sw = new StringWriter();
            HtmlTextWriter htw = new HtmlTextWriter(sw);
            gv.RenderControl(htw);
            resp.Output.Write(sw.ToString());
            resp.Flush();
            resp.End();
        }

        internal bool sendEmail(string strReceiver, string strSubject, string strComment)
        {
            try
            {
                //create the mail message handle, this is given by System.Net.Mail
                MailMessage mailMessage = new MailMessage();
                //This gives the from address for sender
                //First is for the email address and second is for display name
                //Display name can be any but email has to be valid
                mailMessage.From = new MailAddress("abc@hotmail.com", "Contosso University");
                //Add email to be sent to address
                mailMessage.To.Add(strReceiver);
                //Subject for the email
                mailMessage.Subject = strSubject;
                //Body of the email
                mailMessage.Body = strComment;
                //type for email body here I have selected to be HTML
                mailMessage.IsBodyHtml = true;

                //Define smtp handle given by System.Net
                SmtpClient smtpClient = new SmtpClient();
                //Define host, this keeps changing, so check your setting for hotmail
                //Alternatively you can use your gmail also ask smtp server
                smtpClient.Host = "smtp-mail.outlook.com";
                smtpClient.Port = 587;
                smtpClient.EnableSsl = true;

                NetworkCredential networkCredential = new NetworkCredential();
                networkCredential.UserName = "abc@hotmail.com";
                networkCredential.Password = "abcabc";
                smtpClient.UseDefaultCredentials = true;
                smtpClient.Credentials = networkCredential;

                smtpClient.Send(mailMessage);
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }
    }
}

ContactWithEmail.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace ExportToExcelSendEmailandRecaptcha.ViewModel
{
    public class ContactWithEmail
    {
        /*You need not necessary add this ViewModel if you have only one column*/
        [Required(ErrorMessage = "Please enter Comment")]
        public string Comment { get; set; }
    }
}

Contact.cshtml

@model ExportToExcelSendEmailandRecaptcha.ViewModel.ContactWithEmail

@*Recaptcha will work only with public and private key. Please register in website*@
@using Recaptcha.Web.Mvc;
@*Recaptcha will work only with public and private key. Please register in website*@


@{
    ViewBag.Title = "Contact";
}

<h2>Contact</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>ContactWithEmail</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @ViewBag.Message
        <div class="form-group">
            @Html.LabelFor(model => model.Comment, htmlAttributes: new { @class = "control-label col-md-2" })
            @Html.TextAreaFor(model => model.Comment, new { htmlAttributes = new { @class = "form-control" }, rows="5", cols="50" })
            @Html.ValidationMessageFor(model => model.Comment, "", new { @class = "text-danger" })
        </div>
        <div class="form-group">
            @Html.Label("   ", new { @class = "col-sm-2 control-label" })
            @Html.Recaptcha(theme: Recaptcha.Web.RecaptchaTheme.Clean)
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>