I'm fairly new to asp .net MVC, I've got a modal wish accepts a username, email address, comments, and also has a submit button. I'm looking create the submit functionality such that when it's pressed it'll send an email.
I've had passed experience sending emails in c# no problem, the troubles I'm having is linking the two together.
<div class="modal fade" id="contact" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<form class="form-horizontal">
<div class="modal-header">
<h4>Contact Tech Site</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="contact-name" class="col-lg-2 control-label">Name:</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="contact-name" placeholder="Full Name">
</div>
</div>
<div class="form-group">
<label for="contact-email" class="col-lg-2 control-label">Email:</label>
<div class="col-lg-10">
<input type="email" class="form-control" id="contact-email" placeholder="you#example.com">
</div>
</div>
<div class="form-group">
<label for="contact-msg" class="col-lg-2 control-label">Message:</label>
<div class="col-lg-10">
<textarea class="form-control" rows="8"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<a class="btn btn-default" data-dismiss="modal">Close</a>
<button class="btn btn-primary" type="submit">Send</button>
</div>
</form>
</div>
</div>
</div>
Email Code
var SMTP_USERNAME = User.EmailUsername;
var SMTP_PASSWORD = EncryptionHelper.Decrypt(User.EmailPassword);
Mail.Subject = Subject;
Mail.Body = EmailText;
foreach (var to in SelectedUsers)
{
foreach (var contactMethod in to.ContactMethods.Where(x => x.Primary && x.Channel == ContactMethod.Channels.Email))
{
Mail.To.Add(contactMethod.Value);
}
}
Mail.From = new MailAddress(SMTP_USERNAME, User.FullName());
//Server
var HOST = unitOfWork.SettingRepository.GetString(KnownKeys.SMTPServer);
//Port
var PORT = int.Parse(unitOfWork.SettingRepository.GetString(KnownKeys.SMTPPort));
// Create an SMTP client with the specified host name and port.
var emailSent = false;
using (SmtpClient client = new SmtpClient(HOST, PORT))
{
// Create a network credential with your SMTP user name and password.
client.Credentials = new System.Net.NetworkCredential(SMTP_USERNAME, SMTP_PASSWORD);
// Use SSL when accessing Amazon SES. The SMTP session will begin on an unencrypted connection, and then
// the client will issue a STARTTLS command to upgrade to an encrypted connection using SSL.
client.EnableSsl = true;
// Send the email.
try
{
client.Send(Mail);
emailSent = true;
}
catch (Exception ex)
{
MessageBox.Show("Error message: " + ex.Message);
}
}
Create a model -
public class EmailViewModel
{
public string Username { get; set; }
public string Email { get; set; }
public string Comments { get; set; }
}
And then create your controller -
public class HomeController : Controller
{
public ActionResult GetEmailForm()
{
return View();
}
public ActionResult SubmitEmail(EmailViewModel model)
{
var result = SendEamil(model);
return View();
}
private bool SendEamil(EmailViewModel model)
{
// Use model and send email with your code.
return true;
}
}
Basically GetEmailForm action will return you a view with form -
#model MvcApplication1.Controllers.EmailViewModel
#{
ViewBag.Title = "GetEmailForm";
}
<h2>GetEmailForm</h2>
<link href="../../Content/bootstrap.css" rel="stylesheet" />
#using (Html.BeginForm("SubmitEmail", "Home", FormMethod.Post))
{
<div id="contact">
<div class="modal-dialog">
<div class="modal-content">
<form class="form-horizontal">
<div class="modal-header">
<h4>Contact Tech Site</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="contact-name" class="col-lg-2 control-label">Name:</label>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.Username, new { #placeholder = "Full Name"})
</div>
</div>
<div class="form-group">
<label for="contact-email" class="col-lg-2 control-label">Email:</label>
<div class="col-lg-10">
#Html.TextBoxFor(m => m.Email, new { #placeholder = "you#example.com"})
</div>
</div>
<div class="form-group">
<label for="contact-msg" class="col-lg-2 control-label">Message:</label>
<div class="col-lg-10">
#Html.TextAreaFor(m => m.Comments, new { #placeholder = "Comments"})
</div>
</div>
</div>
<div class="modal-footer">
<a class="btn btn-default" data-dismiss="modal">Close</a>
<button class="btn btn-primary" type="submit">Send</button>
</div>
</form>
</div>
</div>
</div>
}
When you enter data and click on submit, it will post the viewmodel with data to SubmitEmail action of same controller.
Output of the page is as shown below, sorry for styles, i have no time so removed some of the styles.
When you enter data and click on submit, you get data as shown below -
Once you have the data, you can use that in your private method SendEmail (which will have your code) to send email.
Check the MSDN site for information on how to create a form, it will get submitted when the user presses the submit button. Back in yoru controller add a second version of your method with the HttpPost attribute and give it a parameter instance of your model, MVC will take care of the mapping for you. See BUILDING ASP.NET MVC FORMS WITH RAZOR for more details.
Call a action method From your Email Controller thru a ajax call.From the below Code Snippet you will get an idea how to do it.
$('#btnSubmit').on('click', function () { //Ur Button
$.ajax({
type: "POST",
url: "/EmailController/SendEmailAction",
data: "{Email:" + $("#contact-email").val() +"}", // Reading from extboxes and Converting to JSON for Post to EmailController Action
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(result) {
//alert message
//Close the Modal
}
});
});
And In C# level in youecontroller
public JsonResult _SendEmail(EmailViewModel model)
{
//Here your code to send Email
}
I hope now you will get an idea how to go about it.
I think you do not require a form and submit button to send an email from a bootstrap modal.
Related
I want to pass data from Textbox value to the controller. The Textbox Value its string and on the controller, it must be converted to double. But I seem to fail on the presented code below. I don't know why the code does not work.
===VIEW CODE===
#using (Html.BeginForm("OnceOff"))
{
<div class="container">
<div class="bg hidden-sm"></div>
<div class="row">
<div class="col">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Once-Off Payment</h3>
</div>
<div class="panel-body">
<input type="text" id="smsbundles" name="smsbundles" value="50" />
</div>
<div class="text-right">
#Html.ActionLink("Buy Now", "OnceOff", "Home", new { area = "" }, new { #class = "btn btn-block btn-success" })
</div>
</div>
</div>
</div>
</div>
}
===CONTROLLER===
public ActionResult OnceOff(string smsbundles)
{
double bundle = Convert.ToDouble(smsbundles);
var onceOffRequest = new PayFastRequest(this.payFastSettings.PassPhrase);
// Merchant Details
onceOffRequest.merchant_id = this.payFastSettings.MerchantId;
onceOffRequest.merchant_key = this.payFastSettings.MerchantKey;
onceOffRequest.return_url = this.payFastSettings.ReturnUrl;
onceOffRequest.cancel_url = this.payFastSettings.CancelUrl;
onceOffRequest.notify_url = this.payFastSettings.NotifyUrl;
// Buyer Details
onceOffRequest.email_address = "";
// Transaction Details
onceOffRequest.m_payment_id = "***";
onceOffRequest.amount = bundle; //30 or 50
onceOffRequest.item_name = "Once off option";
onceOffRequest.item_description = "Some details about the once off payment";
// Transaction Options
onceOffRequest.email_confirmation = true;
onceOffRequest.confirmation_address = "****";
var redirectUrl = $"{this.payFastSettings.ProcessUrl}{onceOffRequest.ToString()}";
return Redirect(redirectUrl);
}
Your input smsbundles is an input element inside a form.
You are using ActionLink helper, that generates <a> element that does not submit the form. That's the reason your controller action code is called with a null value of smsbundles.
Replace you ActionLink to a regular submit button:
<input type="submit" value="Buy Now" class="btn btn-block btn-success" />
On my login page I have a dropdownlist to change the culture of the application for which I am doing a Ajax call to set the culture. By default I have set to 'en_US'.
My issue is when I am login directly without changing the culture I am able to login successfully, but when I change the culture and tries to login, I am not able to do that. Is this happening because of AJAX call made, which makes custom attribute not registered ?
Also, my login method has a custom attribute defined. Below is the code.
AJAX Call
$('#ddlLanguages').change(function () {
var val = $('#ddlLanguages').val()
createCookie('culturecookie', val, 7);
$.ajax({
type: "POST",
url: '/Account/GetCultureNew',
data: { culturename: val },
success: function (result) {
$("#logo-group").html('');
$(document.body).html('');
$(document.body).html(result);
},
error: function (data) {
//alert('Error');
}
});
});
Ajax Method in controller
[HttpPost]
public ActionResult GetCultureNew(string culturename)
{
if (!string.IsNullOrEmpty(culturename) & culturename.Contains("#"))
{
string[] strdata = culturename.Split('#');
if (strdata.Length > 0)
{
AppTenant tenant = HttpContext.Session.GetObjectFromJson<AppTenant>("TenantInfo");
if (tenant != null)
{
tenant.LoggedInCulture = strdata[0];
tenant.LanguageID = Convert.ToInt32(strdata[1]);
HttpContext.Session.SetObjectAsJson("TenantInfo", tenant);
}
}
}
List<SelectListItem> items = new List<SelectListItem>();
items = HttpContext.Session.GetObjectFromJson<List<SelectListItem>>("LanguageData");
foreach (var item in items)
{
if (item.Value == culturename)
{
item.Selected = true;
}
else
{
item.Selected = false;
}
}
var itemsString = JsonConvert.SerializeObject(items);
CookieOptions obj = new CookieOptions();
obj.Expires = DateTime.Now.AddMonths(3);
Response.Cookies.Append("Languagelist", itemsString, obj);
var viewModel = new LMS_User { ReturnUrl = string.Empty, LanguageList = items };
return View("Login", viewModel);
}
Login Method
[HttpPost]
[AllowAnonymous]
[ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)]
[Route("Admin/Login/{clietname}")]
public async Task<IActionResult> Login([Bind(include: "Email,Password,RememberMe")] LMS_User model, string returnUrl)
{
// my login logic
}
EDIT :- 1
Login partial View
<div class="col-xs-12 col-sm-12 col-md-5 col-lg-4">
<div class="well no-padding">
<form action="#Url.Action("login", "account")" method="POST" id="login-form" class="smart-form client-form">
<header>
#obj["SingnIn"]
</header>
#Html.AntiForgeryToken()
<fieldset>
<section>
<label asp-for="LanguageList">#obj["LanguageList"] </label>
#Html.DropDownList("Languages", Model.LanguageList, null, new { id = "ddlLanguages", #class = "form-control" })
</section>
<section>
<label asp-for="Email">#obj["Email"]</label>
<label class="input">
<i class="icon-append fa fa-user"></i>
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
<b class="tooltip tooltip-top-right"><i class="fa fa-user txt-color-teal"></i>>#obj["tooltipEmail"]</b>
<span asp-validation-for="Email" class="text-danger"></span>
</label>
</section>
<section>
<label asp-for="Password">#obj["Password"]</label>
<label class="input">
<i class="icon-append fa fa-lock"></i>
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
<b class="tooltip tooltip-top-right"><i class="fa fa-lock txt-color-teal"></i>#obj["tooltippassword"] </b>
<span asp-validation-for="Password" class="text-danger"></span>
</label>
<div class="note">
<i class="fa fa-frown-o"></i> #obj["Forgot_password?"]
</div>
</section>
<section>
<label class="checkbox">
<input asp-for="RememberMe" />
<i></i>#obj["Remember_Me"]
</label>
</section>
<footer>
<button type="submit" class="btn btn-primary">
#obj["SingnIn"]
</button>
</footer>
</fieldset>
</form>
</div>
#{ await Html.RenderPartialAsync("_SocialMedia"); }
Edit 2:-Entire login view
<div id="content" class="container">
<div class="row">
#{ await Html.RenderPartialAsync("_LoginText"); }
#{ await Html.RenderPartialAsync("_LoginPartial"); }
</div>
</div>
However if I add location.reload() in AJAX success function, then by changing the culture I can login successfully.
Any help on this appreciated !
When you do the $(document.body).html(result);
The action part of the form goes missing. Hence it does not know where to post to.
Hope i have been of some help :)
net mvc 5 application and for this I use bootstrap because it looks fine.
I don't want to use for an input and a searchbutton the
#using (Html.BeginForm("...
Can I control the html tags without this from my controller. For example here is my index.cshtml
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container">
<div class="row">
<h2>Suche</h2>
<div id="custom-search-input">
<div class="input-group col-md-12">
<input type="text" class=" search-query form-control" placeholder="Search" />
<span class="input-group-btn">
<button class="btn btn-danger" type="button">
<span class=" glyphicon glyphicon-search"></span>
</button>
</span>
</div>
</div>
</div>
</div>
I want if I click on the Searchbutton I get a message with the text from the inputfield.
Here is the Controller:
public ActionResult Search(string value)
{
//listofUsers is a arraylist of all users that found^^
return View(listofUsers);
}
How I can do this? :)
Add a div to show the result:
<div id="custom-search-input">
<div class="input-group col-md-12">
<input type="text" class=" search-query form-control" placeholder="Search" />
<span class="input-group-btn">
<button class="btn btn-danger" type="button">
<span class=" glyphicon glyphicon-search"></span>
</button>
</span>
</div>
</div>
<div class="custom-search-result"></div>
Then in a script tag or a linked js file:
$(document).ready(function () {
$('.custom-search-input').each(function () {
var sinput = $(this);
var svalue = sinput.find('input');
var sresult = sinput.next('.custom-search-result');
sinput.find('button').click(function () {
$.ajax({
url: '/ControllerName/Search?value=' + svalue.val(),
type: 'GET'
}).done(function (result) {
sresult.html(result);
});
});
});
});
This is a basic example with no error handling.
First I highly recommend reading Philip Walton (Google) - Decoupling your HTML, CSS and Javascript, it's extremely good.
Here how I would use MVC to it's full potential.
Model:
// Extensible Programming
// Using a string limits additional features
// Future proofing via a class that takes 2 minutes to create
public class GlobalSearch
{
public string SearchTerms { get; set; }
}
View:
#Model GlobalSearch
<div class="container">
<div class="row">
<h2>Suche</h2>
<div id="custom-search-input">
#using (Html.BeginForm("Search"))
{
<div class="input-group col-md-12">
#Html.TextBoxFor(m => m.SearchTerms, new {
#class="search-query form-control",
placeholder="Search" })
<span class="input-group-btn">
<button class="btn btn-danger" type="button">
<span class=" glyphicon glyphicon-search js-form-submit"></span>
</button>
</span>
</div>
}
</div>
</div>
</div>
Controller:
// Strongly Typed Class is Returned
public ActionResult Search(GlobalSearch search)
{
return View(listofUsers);
}
The following script will require this fantastic script called form2js which correctly converts any strongly-typed forms generated by MVC (arrays, lists etc) into Json that will be ModelBinded correctly.
$(document).ready(function() {
('.js-form-submit').on('click', function() {
var $form = $(this).closest('form');
var json = form2js($form);
var ajaxSettings = {
url: $form.attr('action'),
type: $form.attr('method'),
data: json,
contentType: "application/json",
}
$.ajax(ajaxSettings)
.done()
.always()
.fail();
});
});
Of course this could be easily abstract into it's own javascript class/namespace that returns the promise and reusable on any form that simply has a button with the class js-form-submit instead of continually rewriting $.ajax over and over again each time for different forms.
I have an c# MVC application that I'm building, and I'm wondering how to display a modal, containing a please wait message, while files are being uploaded.
I've searched Goggle and this site a lot but I could use some more direct feedback.
I've created the modal in my index.cshtml but am unsure how to display it during the upload process. I tried using something like this in my submit button but it doesn't post the form then.
data-toggle="modal" data-target="#myModal"
This is my code.
Index.cshtml
<h4>Please fill out the form below and select at least one file to upload.</h4>
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="row">
<div class="col-md-2">
<h5>Your Name:</h5>
</div>
<div class="col-md-4">
<input type="text" name="uname" class="form-control" required placeholder="John Smith">
</div>
</div>
<div class="row">
<div class="col-md-2">
<h5>Your Email:</h5>
</div>
<div class="col-md-4">
<input type="email" name="email" class="form-control" required placeholder="test#test.com">
</div>
</div>
<div class="row">
<div class="col-md-2">
<h5>Your Company:</h5>
</div>
<div class="col-md-4">
<input type="text" name="company" class="form-control" required placeholder="Test Company, Inc">
</div>
</div>
<div class="row">
<div class="col-md-2">
<h5>Choose file(s) to upload (Max 500MB):</h5>
</div>
<div class="col-md-4">
<input name="files" type="file" id="files" multiple="multiple" class="form-control" required />
</div>
</div>
<div class="row">
<div class="col-md-2">
<h5></h5>
</div>
<div class="col-md-4">
<input type="submit" name="submit" value="Upload" class="btn btn-primary" />
</div>
</div>
}
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
Please wait while we are uploading your files
<div class="progress">
<div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%">
</div>
</div>
</div>
</div>
</div>
</div>
Then here is my controller
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Net.Mail;
namespace vidup.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(List<HttpPostedFileBase> files)
{
var userName = Request["uname"].ToString();
var userEmail = Request["email"].ToString();
var userCompany = Request["company"].ToString();
ViewBag.Username = userName;
ViewBag.UserCompany = userCompany;
ViewBag.UserEmail = userEmail;
int i = 0;
var path = Path.Combine(Server.MapPath("~/Uploads"), userCompany, userName, DateTime.Now.ToString("MM-dd-yyyy h-mm-tt"));
if (!Directory.Exists(path))
{
DirectoryInfo di = Directory.CreateDirectory(path);
}
foreach (HttpPostedFileBase item in files)
{
i++;
if (item != null && item.ContentLength > 0)
{
var fileName = Path.GetFileName(item.FileName);
var fullPath = Path.Combine(path, fileName);
ViewBag.Message3 = fileName;
ViewBag.Message4 = fullPath;
try
{
item.SaveAs(fullPath);
var fileCount = i + " File(s) uploaded successfully";
ViewBag.Message = fileCount;
}
catch (Exception e)
{
ViewBag.Message = e;
}
}
else
{
ViewBag.Message = "No File selected";
}
}
return View("Status");
}
}
}
finally the status.cshtml
<h2>Upload Status</h2>
<h4>Thank you, #ViewBag.UserName from #ViewBag.UserCompany</h4>
<P>Your file upload returned a status of: #ViewBag.Message</P>
<p>An Email has been sent to #ViewBag.UserEmail with the status of this upload.</p>
<br/>
Click here to upload again
The reason your submit button does not post the form anymore is because the attributes you put in it are overriding its default behaviour - you would need to add an onclick handler to it to also start the form submit in addition to the modal show. Give your submit button an ID and give your form an ID.. after that its a straightforward onclick method
$('buttonid').on('click', function()
{
$('#formid').submit();
});
This tells your button to submit the form whenever it is clicked
I need to submit data via AJAX, but only an empty string reaches the ActivateUser Method.
Here is the Markup
#model String
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Benutzer aktivieren</h4>
</div>
<div class="modal-body">
<div id="activateresult"></div>
<div style="display: none" id="activateUserSuccess" class="alert alert-success">Der Benutzer konnte erfolgreich aktiviert werden :)</div>
<div style="display: none" id="activateUserFailure" class="alert alert-danger">Leider konnte der Benutzer nicht aktiviert werden :(</div>
<div class="list-group">
#foreach (var item in #deactivatedUsers) {
using (Ajax.BeginForm("ActivateUser", "Settings", new AjaxOptions() {
HttpMethod = "POST",
OnSuccess = "activateSuccess(response)",
OnFailure = "activateFailure(jqXHR, textStatus, errorThrown)",
UpdateTargetId = "activateresult"
}, new {
#class = "list-group-item"
})) {
<h4>
#item.Username
#Html.Hidden("Username")
</h4>
<input class="btn btn-success" type="submit" name="#item.ID" value="Aktivieren" />
}
}
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Fertig</button>
</div>
</div>
</div>
And here is the Controller method
[HttpPost]
public ActionResult ActivateUser(string username) {
try {
customerModel.ActivateUser(username);
return new JsonResult() { Data = true };
} catch (Exception ex) {
return new JsonResult() { Data = false };
}
}
You can the the whole code on github
What am I doing wrong?
Try switching this:
#Html.Hidden("Username")
to this:
#Html.Hidden("username", item.Username)
The parameter to your action is lowercase, and I believe that it is case-sensitive.
Furthermore, that second parameter I am passing in is the value parameter. Without that, I believe framework is going to look for a Username property on the Model. But here you have a username property on item. So the framework wouldn't be able to find the username even with the lowercase correction. You need to explicitly pass in the value in this case.
You can verify you're creating the right thing by looking at the generated HTML in your browser. You want to make sure that your input field is actually named username and that its value is actually the current user's username.