Override action method using plugin into nopCommerce3.8
Tags: nopcommerce, nopcommerceplugin, csharp
Published: 2020-02-11 05:52:14

This article learn you how to override the action method in nopcommerce 3.8 version. In this article i am going to overrride the contact us form to extend its funcationliy. but this action method override way is not worked over seo url(route value) like product url,category url etc. 
 
Now i am going to show how to override the contact us page using plugin. This contact us form having only field like name,emailid,content but i want to add one more field that is contact no that help me to get contact detail of person who going to post this form.
 
For this feature i am going to add one project into plugin folder and add the ContactusController.cs, RouteProvider.cs,ContactUsModel.cs, ContactUs.cshtml, app.config,description.txt,OverrideActionMethodProvider.cs, packages.config, web.config. for now i have refer the Nop.Plugin.ExternalAuth.Facebook plugin.
 
My plugin structure is as describe with this article.
 
I have created
ContactSscontroller.cs =>  for contact us form get or post method.
RouteProvider.cs => used to over ride the route url of contact us. if user call the contact us url then our plugin form will be display instead of default nopcommerce form(action method). 
ContactUsmodel.cs => to add one more property of contact no.
ContactUs.cshtml => This view file to display content of contact us form
OverrideActionMethodProvider.cs => having method of install and uninstall process for plugin.
 
 
 ContactUsmodel.cs model file. I have added my new property into this model. I have used the existing ContactUsModel of nopcommerce.
using Nop.Web.Framework;  
 


	namespace Nop.Plugin.OverrideActionMethod.Models  
	{  
		public class ContactUsModel : Nop.Web.Models.Common.ContactUsModel  
		{  
			[NopResourceDisplayName("Account.Fields.Phone")]          
			public string PhoneNo { get; set; }  
		}  
	}  

 
RouteProvider.cs routeProvider file override the existing route value 

	using Nop.Web.Framework.Localization;  
	using Nop.Web.Framework.Mvc.Routes;  
	using System.Web.Routing;  
	using System.Linq;  

	namespace Nop.Web.Infrastructure  
	{  
		public partial class RouteProvider : IRouteProvider  
		{  
			public void RegisterRoutes(RouteCollection routes)  
			{  
				routes.Remove(routes.FirstOrDefault(c => (c as Route).Url == "contactus"));  
				routes.MapLocalizedRoute("ContactUs",  
								 "contactus",  
								 new { controller = "ContactUs", action = "ContactUs" },  
								 new[] { "Nop.Plugin.OverrideActionMethod.Controllers" });  
			}    
		}  
	}   

I have remove the existing route value of contact us and add my contact us route value. I have mention my controller name, action methon name and namespace for this. 
 
 
 Contactus.cshtml view file  

	@model ContactUsModel  
	@using Nop.Plugin.OverrideActionMethod.Models  
	@using Nop.Web.Framework  
	@using Nop.Web.Framework.UI  
	@using Nop.Web.Framework.Security.Captcha   
	@{  
		Layout = "~/Views/Shared/_ColumnsOne.cshtml";  
	  
		//title  
		Html.AddTitleParts(T("PageTitle.ContactUs").Text);  
		//page class  
		Html.AppendPageCssClassParts("html-contact-page");  
	}  
	<div class="page contact-page">  
		<div class="page-title">  
			<h1>@T("PageTitle.ContactUs")</h1>  
		</div>  
		<div class="page-body">  
			@Html.Action("TopicBlock", "Topic", new { systemName = "ContactUs" })  
			@Html.Widget("contactus_top")  
			@if (Model.SuccessfullySent)  
			{  
				<div class="result">  
					@Model.Result  
				</div>  
			}  
			else  
			{  
				using (Html.BeginForm("ContactUsSend", "ContactUs", FormMethod.Post, new { id = "form" }))  
				{  
					@Html.AntiForgeryToken()  
					var validationSummary = Html.ValidationSummary(true);  
					if (!MvcHtmlString.IsNullOrEmpty(validationSummary))  
					{  
						<div class="message-error">@validationSummary</div>  
					}  
					<div class="fieldset">  
						<div class="form-fields">  
							<div class="inputs">  
								@Html.LabelFor(model => model.FullName)  
								@Html.TextBoxFor(model => model.FullName, new { @class = "fullname", placeholder = T("ContactUs.FullName.Hint") })  
								@Html.RequiredHint()  
								@Html.ValidationMessageFor(model => model.FullName)  
							</div>  
							<div class="inputs">  
								@Html.LabelFor(model => model.Email)  
								@Html.TextBoxFor(model => model.Email, new { @class = "email", placeholder = T("ContactUs.Email.Hint") })  
								@Html.RequiredHint()  
								@Html.ValidationMessageFor(model => model.Email)  
							</div>  
							@if (Model.SubjectEnabled)  
							{  
								<div class="inputs">  
									@Html.LabelFor(model => model.Subject)  
									@Html.TextBoxFor(model => model.Subject, new { @class = "subject", placeholder = T("ContactUs.Subject.Hint") })  
									@Html.RequiredHint()  
									@Html.ValidationMessageFor(model => model.Subject)  
								</div>  
							}  
							<div class="inputs">  
								@Html.LabelFor(model => model.Enquiry)  
								@Html.TextAreaFor(model => model.Enquiry, new { @class = "enquiry", placeholder = T("ContactUs.Enquiry.Hint") })  
								@Html.RequiredHint()  
								@Html.ValidationMessageFor(model => model.Enquiry)  
							</div>  
							@if (Model.DisplayCaptcha)  
							{  
								<div class="captcha-box">  
									@Html.Raw(Html.GenerateCaptcha())  
								</div>  
							}  
	  
							<div class="inputs">  
								@Html.LabelFor(model => model.PhoneNo)  
								@Html.TextBoxFor(model => model.PhoneNo)  
								@Html.ValidationMessageFor(model => model.PhoneNo)  
							</div>  
						</div>  
					</div>  
					<div class="buttons">  
						<input type="submit" name="send-email" class="button-1 contact-us-button" value="@T("ContactUs.Button")" />  
					</div>  
				}  
			}  
			@Html.Widget("contactus_bottom")  
		</div>  
	</div>  

 I have only add phone no text into this view file and change the form post action method name to post into my controller
 
 
ContactUsController.cs 

	using Nop.Core;  
	using Nop.Core.Domain.Common;  
	using Nop.Core.Domain.Messages;  
	using Nop.Plugin.OverrideActionMethod.Models;  
	using Nop.Services.Customers;  
	using Nop.Services.Localization;  
	using Nop.Services.Logging;  
	using Nop.Services.Messages;  
	using Nop.Web.Controllers;  
	using Nop.Web.Framework.Security;  
	using Nop.Web.Framework.Security.Captcha;  
	using System;  
	using System.Linq;  
	using System.Web.Mvc;  
	  
	  
	namespace Nop.Plugin.OverrideActionMethod.Controllers  
	{  
		public class ContactUsController : BasePublicController  
		{  
			#region Fields  
	  
			private readonly ILocalizationService _localizationService;  
			private readonly IWorkContext _workContext;  
			private readonly IStoreContext _storeContext;  
			private readonly IQueuedEmailService _queuedEmailService;  
			private readonly IEmailAccountService _emailAccountService;  
			private readonly ICustomerActivityService _customerActivityService;  
			private readonly EmailAccountSettings _emailAccountSettings;  
			private readonly CommonSettings _commonSettings;  
			private readonly CaptchaSettings _captchaSettings;  
	 
			#endregion  
	 
			#region Constructors  
	  
			public ContactUsController(  
				ILocalizationService localizationService,  
				IWorkContext workContext,  
				IStoreContext storeContext,  
				IQueuedEmailService queuedEmailService,  
				IEmailAccountService emailAccountService,  
				ICustomerActivityService customerActivityService,  
				EmailAccountSettings emailAccountSettings,  
				CommonSettings commonSettings,  
				CaptchaSettings captchaSettings)  
			{  
				this._localizationService = localizationService;  
				this._workContext = workContext;  
				this._storeContext = storeContext;  
				this._queuedEmailService = queuedEmailService;  
				this._emailAccountService = emailAccountService;  
				this._customerActivityService = customerActivityService;  
				this._emailAccountSettings = emailAccountSettings;  
				this._commonSettings = commonSettings;  
				this._captchaSettings = captchaSettings;  
			}  
	 
			#endregion  
	 
			#region Methods  
	  
			public ActionResult ContactUs()  
			{  
				var model = new ContactUsModel  
				{  
					Email = _workContext.CurrentCustomer.Email,  
					FullName = _workContext.CurrentCustomer.GetFullName(),  
					SubjectEnabled = _commonSettings.SubjectFieldOnContactUsForm,  
					DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnContactUsPage  
				};  
				return View("~/Plugins/Plugin.OverrideActionMethod/Views/ContactUs/ContactUs.cshtml", model);  
			}  
	  
			[HttpPost]  
			[PublicAntiForgery]  
			[CaptchaValidator]  
			public ActionResult ContactUsSend(ContactUsModel model, bool captchaValid)  
			{  
				//validate CAPTCHA  
				if (_captchaSettings.Enabled && _captchaSettings.ShowOnContactUsPage && !captchaValid)  
				{  
					ModelState.AddModelError("", _captchaSettings.GetWrongCaptchaMessage(_localizationService));  
				}  
	  
				if (ModelState.IsValid)  
				{  
					var phoneNo = model.PhoneNo;  
					string email = model.Email.Trim();  
					string fullName = model.FullName;  
					string subject = _commonSettings.SubjectFieldOnContactUsForm ?  
						model.Subject :  
						string.Format(_localizationService.GetResource("ContactUs.EmailSubject"), _storeContext.CurrentStore.GetLocalized(x => x.Name));  
	  
					var emailAccount = _emailAccountService.GetEmailAccountById(_emailAccountSettings.DefaultEmailAccountId);  
					if (emailAccount == null)  
						emailAccount = _emailAccountService.GetAllEmailAccounts().FirstOrDefault();  
					if (emailAccount == null)  
						throw new Exception("No email account could be loaded");  
	  
					string from;  
					string fromName;  
					string body = Core.Html.HtmlHelper.FormatText(model.Enquiry, false, true, false, false, false, false);  
					//required for some SMTP servers  
					if (_commonSettings.UseSystemEmailForContactUsForm)  
					{  
						from = emailAccount.Email;  
						fromName = emailAccount.DisplayName;  
						body = string.Format("<strong>From</strong>: {0} - {1}<br /><br />{2}",  
							Server.HtmlEncode(fullName),  
							Server.HtmlEncode(email), body);  
					}  
					else  
					{  
						from = email;  
						fromName = fullName;  
					}  
					_queuedEmailService.InsertQueuedEmail(new QueuedEmail  
					{  
						From = from,  
						FromName = fromName,  
						To = emailAccount.Email,  
						ToName = emailAccount.DisplayName,  
						ReplyTo = email,  
						ReplyToName = fullName,  
						Priority = QueuedEmailPriority.High,  
						Subject = subject,  
						Body = body,  
						CreatedOnUtc = DateTime.UtcNow,  
						EmailAccountId = emailAccount.Id,  
					});  
	  
					model.SuccessfullySent = true;  
					model.Result = _localizationService.GetResource("ContactUs.YourEnquiryHasBeenSent");  
	  
					//activity log  
					_customerActivityService.InsertActivity("PublicStore.ContactUs", _localizationService.GetResource("ActivityLog.PublicStore.ContactUs"));  
	  
					return View("~/Plugins/Plugin.OverrideActionMethod/Views/ContactUs/ContactUs.cshtml", model);  
				}  
	  
				model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnContactUsPage;  
				return View("~/Plugins/Plugin.OverrideActionMethod/Views/ContactUs/ContactUs.cshtml", model);  
			}  
			#endregion  
		}  
	}  



This controller help me to display my contact us form and get the form detail into my end to get new property value. 
 
 
I hope you got the way to override the action method using plugin in nopcommerce3.8. I have attached the source code of this plugin so you can able to get better idea for this. 
 
 
 https://www.mediafire.com/file/ze6ck5u2wsho0qk/Nop.Plugin.OverrideActionMethod.zip/file