using HttpPost annotation? Fix so it does not break page - c#

I am building an MVC email form and everything on the tutorial page works except if I keep [HttpPost] the page breaks.
I dont think I am forgeting an Import.
What will fix this so the Email Form will post or rather [HttpPost] will not cause the error?
I also tried [System.Web.Mvc.HttpPost]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Net.Mail;
using System.Text;
using SW.Models;
namespace SW.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
//ViewBag.Message = "Your application description page.";
return View();
}
//[System.Web.Mvc.HttpPost]
public ActionResult Contact(ContactModels c)
{
//ViewBag.Message = "Your contact page.";
if (ModelState.IsValid)
{
try
{
MailMessage msg = new MailMessage();
SmtpClient smtp = new SmtpClient();
MailAddress from = new MailAddress(c.Email.ToString());
StringBuilder sb = new StringBuilder();
msg.To.Add("mail#hotmail.com");
msg.Subject = "Contact Us";
msg.IsBodyHtml = false;
smtp.Host = "mail.mail.com";
smtp.Port = 25;
sb.Append("First name: " + c.FirstName);
sb.Append(Environment.NewLine);
sb.Append("Last name: " + c.LastName);
sb.Append(Environment.NewLine);
sb.Append("Email: " + c.Email);
sb.Append(Environment.NewLine);
sb.Append("Comments: " + c.Comment);
smtp.Send(msg);
msg.Dispose();
return View("Success");
}
catch (Exception)
{
return View("Error");
}
}
return View();
}
}
}
As Soon as I goto Contact I get the error:
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Home/Contact
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18446

It's hard to say for sure without knowing what error message you are getting, but I think this is the problem: You'll want to have separate GET and POST methods for the Contact() action. The GET handles the case where you are viewing the contact page. The POST handles the case where you are submitting your form.
It might look something like this:
[System.Web.Mvc.HttpGet]
public ActionResult Contact()
{
return View(new ContactModels());
}
[System.Web.Mvc.HttpPost]
public ActionResult Contact(ContactModels c)
{
//ViewBag.Message = "Your contact page.";
if (ModelState.IsValid)
{
try
{
MailMessage msg = new MailMessage();
SmtpClient smtp = new SmtpClient();
MailAddress from = new MailAddress(c.Email.ToString());
StringBuilder sb = new StringBuilder();
msg.To.Add("mail#hotmail.com");
msg.Subject = "Contact Us";
msg.IsBodyHtml = false;
smtp.Host = "mail.mail.com";
smtp.Port = 25;
sb.Append("First name: " + c.FirstName);
sb.Append(Environment.NewLine);
sb.Append("Last name: " + c.LastName);
sb.Append(Environment.NewLine);
sb.Append("Email: " + c.Email);
sb.Append(Environment.NewLine);
sb.Append("Comments: " + c.Comment);
smtp.Send(msg);
msg.Dispose();
return View("Success");
}
catch (Exception)
{
return View("Error");
}
}
return View();
}
If you have only a single method with an HttpPost attribute, it's only available for HTTP POST requests, so attempting to HTTP GET the page in your web browser will fail.

Actions without attributes are by default GET methods. If you add the explicit HttpPost attribute to your method, it will no longer work for GET requests, such as displaying the contacts page in the first place.
You can use the [AcceptVerbs(HttpVerbs.Get|HttpVerbs.Post)] attribute syntax to allow both.

You have to have both Get and Post actions or remove the HttpPost attribute and assign your form method to "GET".

Related

ASP.NET Core Web API POST request works with Postman but not in C#/React

I have a Contact Us page created in React that has three fields(Name,Email,Message), when I click the Submit button, it does not send an email to the specified user. When I used Postman to test my Web API created in C#, it sends the email correctly. I don't know what's happening since it does not throw any error.
I'm using using using System.Net.Mail; to perform smtp emails.
Here is my web api code:
[HttpPost]
public void Post(Contact contact)
{
using (SmtpClient client = new SmtpClient("smtp.gmail.com", 587))
{
MailAddress to = new MailAddress(contact.Email);
MailAddress from = new MailAddress(_email);
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(_email, _password);
client.EnableSsl = true;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
using (MailMessage message = new MailMessage(from, to))
{
message.Subject = $"Hello {contact.Name}...";
message.Body = contact.Message;
try
{
client.Send(message);
}
catch (SmtpException smtp)
{
Console.WriteLine(smtp);
}
}
}
Here is my React code:
useEffect(() => {
if (trigger) {
axios({
method: "post",
url: `${proxy} + ${url}`,
headers: { "Content-Type": "application/json" },
data: data,
}).then((response) => {
console.log(response.config.data);
});
}
}, [trigger]);
// My code performs post request when the submit button is changed.
// When the submit button is clicked,it sets the trigger's state to true to perform the post request.
Screenshot:
Edit: Added Request Headers + Response Tab:
Edit: Added Project Structure

MVC Email Issue

Here are my two actions for sending emails via MVC:
[HttpGet]
// GET: EmailForms
public ActionResult EmailForm(int id)
{
EmailFormModel emailModel = new EmailFormModel();
ChosenWT cwt = new ChosenWT();
OInfo person= new OInfo();
using (var db = new OWTEntities())
{
cwt = db.ChosenWTs.Find(id);
person= db.OInfoes.Find(cwt.OID);
}
emailModel.Message = "This is paragraph 1.\n\nThis is paragraph 2.\n\nThis is paragraph 3." // issue deals with this property
emailModel.FromEmail = User.Identity.Name.Split('\\')[1] + "#domain.com";
string Logon = Common.GetLogon(person.IBM);
emailModel.ToEmail = Logon + "#domain.com";
return View(emailModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> EmailForm(EmailFormModel model)
{
if (ModelState.IsValid)
{
var body = "<p>Email From: {0} ({1})</p><p>Message:</p><p>{2}</p>";
var message = new MailMessage();
message.To.Add(new MailAddress(model.ToEmail));
message.From = new MailAddress(model.FromEmail);
message.Subject = "Test Program";
message.Body = string.Format(body, model.FromName, model.FromEmail, model.Message); // This doesn't keep the paragraph formatting like in the [HttpGet] Action.. Instead it just combines it all into 1 big paragraph..
message.IsBodyHtml = true;
using (var smtp = new SmtpClient())
{
smtp.Host = "smtp.test.server";
await smtp.SendMailAsync(message);
return RedirectToAction("Index", "OInfoes");
}
}
return View(model);
}
If you read the comments I put in the code above, that is the issue with this code.
I can format the Message so that when the user first comes to the page, the string is formatted into paragraph form.. but when I click Send, the HttpPost Action takes the message and ignores the \n\n and combines it all into one giant paragraph.
So I have tried to include <p></p> symbols into the string, but when I hit submit, I get an error stating that those characters are potentially dangerous.
Is there a way for the formatting to stay the same when i submit?
Any help is appreciated.
The reason why you are getting the error is, when a form is submitted, the asp.met mvc framework will inspect the request body to see whether it has any potentially dangerous content as HTML markup(Think about script injection). If it detects any dangerous content,the Request Validation module will throw an error. This is by design
You can apply AllowHtml attribute to the property which holds the html markup in your view model class so that the request validation framework won't reject the data submitted.
public class EmailFormModel
{
[AllowHtml]
public string Message { set;get;}
public string FromEmail {set;get;}
//Other properties of view model goes here
}

Send e-mail in C# ASP.NET with parameters passed in from URL

I should mention this is just a learning project, and will never be hosted online. I am running the app locally.
I'm having two problems sending email with parameters passed in:
The main problem: it doesn't send.
The parameters don't populate the form in the view until after clicking send and redirecting to the same page, however they are displaying in the URL.
Here is my code:
Mail.cs (Model)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LotManager.Models
{
public class Mail
{
public string From = "myusername#gmail.com";
public string To { get; set; }
public string Subject = "Parking Alert";
public string Body { get; set; }
}
}
MailController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Web;
using System.Web.Mvc;
using LotManager.Controllers;
namespace LotManager.Controllers
{
public class MailController : Controller
{
//
// GET: /SendMailer/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ViewResult Index(LotManager.Models.Mail _objModelMail)
{
var to = Request.QueryString["To"];
ViewBag.To = to;
var body = Request.QueryString["Body"];
ViewBag.Body = body;
if (ModelState.IsValid)
{
MailMessage mail = new MailMessage();
mail.To.Add(to);
mail.From = new MailAddress(_objModelMail.From);
string Body = body;
mail.Body = Body;
mail.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com";
smtp.Port = 25;
smtp.UseDefaultCredentials = false;
smtp.Credentials = new System.Net.NetworkCredential
("mygmailusername", "mypassword"); //My actual account info goes here
smtp.EnableSsl = true;
try
{
smtp.Send(mail);
}
catch (Exception)
{
Console.WriteLine("The email was not sent, because I couldn't get it to work. Oops!");
}
return View("Index", _objModelMail);
}
else
{
return View();
}
}
}
}
Index.cshtml (Send Mail View)
#model LotManager.Models.Mail
#{
ViewBag.Title = "Send";
}
<h2>Send</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary()
<p>To: </p>
<p>#Html.TextBoxFor(m => m.To, new { #Value = #ViewBag.To })</p>
<p>Body: </p>
<p>#Html.TextBoxFor(m => m.Body, new { #Value = #ViewBag.Body })</p>
<input type="submit" value="Send" />
}
The code that passes the parameters to the URL:
#Html.Actionlink("Send Notification", "Index", "Mail", new { To = item.Employee.Email, Body = item.Description }, null)
A malicious user can use your page to spam people using your email account. That will quickly destroy your sender reputation with Gmail. It can be nearly impossible to recover from a badly tarnished sender reputation.
Issue 1
You're using the wrong SMTP port.
smtp.gmail.com requires port 465 for SSL or port 587 for TLS.
Issue 2
You are invoking the controller using a link (ActionLink), which creates a GET request. Your controller action will only be invoked for a POST however due to the [HttpPost] attribute. Either remove [HttpPost], or use a post action rather than a link to invoke the controller action.
The parameters are nor avialliable, becasue You are using [HttpPost]. Paramters are visible in GET not in POST.
About second problem look at Google documentation: https://support.google.com/a/answer/176600?hl=en
If you want to use port 25 you need to change server to smtp-relay.gmail.com. Otherwise change port to 465 for SSL or port 587 for TLS.

How to upload a file to be an attachment in an email?

I have a form but the user's data is not stored anywhere, just sent in an email. Does anyone know of an easy way to allow the user to attach a file?
As of now, when the user clicks submit, jquery collects the data and sends it to 'AjaxController.cs'. (A form element is not used)
HTML
<div class="form">
<input type="text" name="Name">
<input type="file" name="File">
<button>Submit</button>
</div>
JS
$(document).ready(function(){
$('button').click(function(){
var data = {};
$('input').each(function(){
data[this.name] = this.value;
}
$.post('/Ajax/Email', data, function(){
alert("Email Sent");
});
});
}
C#
public class AjaxController : Controller
{
public ActionResult Email()
{
MailMessage message = new MailMessage("from#fake.com","marketing#fake.com");
foreach (string form_inputs in Request.Form.Keys)
{
String input_name = form_inputs.ToString();
String input_value = Request.Form[form_inputs].Trim();
if(input_name == "File")
{
System.Net.Mail.Attachment attachment;
attachment = new System.Net.Mail.Attachment(input_value); //ERROR
message.Attachments.Add(attachment);
}
if (input_name == "Name")
{
message.Body = "Name: " + input_value;
}
}
SmtpClient client = new SmtpClient();
client.Port = 25;
client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Host = "SMTP.fake.com";
client.Send(message);
}
}
/Ajax/Email simply returns 'Mail Sent!"
I'm getting an error that basically says the uploaded file does not exist locally - of course - because it hasn't been uploaded. Where does the file exist at this point, how do I access it?
Files uploaded in MVC are in the Request collection as an HttpPostedFileBase type. You can use this to get a stream instance of the file in memory on the server and attach it directly to the e-mail. When using a FORM tag, you must set the the enctype="multipart/form-data" in your form.
In your controller:
public class AjaxController : Controller
{
public ActionResult Email()
{
MailMessage message = new MailMessage("from#fake.com","marketing#fake.com");
foreach (string form_inputs in Request.Form.Keys)
{
String input_name = form_inputs.ToString();
String input_value = Request.Form[form_inputs].Trim();
if(input_name == "File")
{
HttpPostedFileBase file = Request.Files[input_name];
System.Net.Mail.Attachment attachment;
attachment = new System.Net.Mail.Attachment(file.InputStream, file.FileName); //ERROR
message.Attachments.Add(attachment);
}
if (input_name == "Name")
{
message.Body = "Name: " + input_value;
}
}
SmtpClient client = new SmtpClient();
client.Port = 25;
client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Host = "SMTP.fake.com";
client.Send(message);
}
}
I also feel compelled to mention the fact that this could be VERY insecure (dangerous) depending on how you're planning to implement this. Please be sure to perform some verification on the file prior to sending it (in memory Virus scan / content type restrictions, etc...).
Because you're using Ajax (which the POST method uses under the covers), you'll have some additional challenges. Up until recently, Ajax file uploads had to be done with an iframe hack. With modern browsers that support XHR2, it can be done only using the FormData object in JavaScript. Luckily, these factors won't affect the server-side code. See this Question for more detail on this:
jQuery Ajax File Upload
For more on using FormData, see here: Sending multipart/formdata with jQuery.ajax
Here is an in-depth article discussing ajax form uploads: http://abandon.ie/notebook/simple-file-uploads-using-jquery-ajax

Send simple Email ASP.NET MVC, IIS7

i'm try to send some simple email to for example test#blabla.com
First of all, I've already tried it in my Localhost, and it worked, the problem was when i uploaded it to my Server
the Server i'm using is windows server 2012 R2, with IIS 7 (not really sure with the version but i believe it's 7 and above)
hosted successfully with no problem, just the send email method don't work...
I've already add SMTP feature, set the SMTP E-MAIL(Yes, there are no SMTP Virtual server in IIS 7 and above)
here's my controller
public ActionResult SendTestEmail()
{
var test_address = "test#blabla.com";
try
{
// Initialize WebMail helper
WebMail.SmtpServer = "localhost";
WebMail.SmtpPort = 25; // Or the port you've been told to use
WebMail.EnableSsl = false;
WebMail.UserName = "";
WebMail.Password = "";
WebMail.From = "admin#testserver.com"; // random email
WebMail.Send(to: test_address,
subject: "Test email message",
body: "This is a debug email message"
);
}
catch (Exception ex)
{
ViewBag.errorMessage = ex.Message; // catch error
}
return View();
}
here is my SMTP E-mail settings:
the error message are: Mailbox unavailable. The server response was: 5.7.1 Unable to relay for test#blabla.com (this happens when i leave the E-mail address textbox empty, this also happens when i've entering any email format such as sample#email.com / my primary e-mail)
You need to set your smtp settings to a real smtp server....
Try some smtp servers off this list if you don't have access to your own...
Here's a nice bit of code for you... Taken from here
MailModel.cs
public class MailModel
{
public string From { get; set; }
public string To { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
SendMailerController.cs - Notice where the smtp settings are stated
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Web;
using System.Web.Mvc;
namespace SendMail.Controllers
{
public class SendMailerController : Controller
{
// GET: /SendMailer/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ViewResult Index(SendMail.Models.MailModel _objModelMail)
{
if (ModelState.IsValid)
{
MailMessage mail = new MailMessage();
mail.To.Add(_objModelMail.To);
mail.From = new MailAddress(_objModelMail.From);
mail.Subject = _objModelMail.Subject;
string Body = _objModelMail.Body;
mail.Body = Body;
mail.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com";
smtp.Port = 587;
smtp.UseDefaultCredentials = false;
smtp.Credentials = new System.Net.NetworkCredential
("username", "password");// Enter senders User name and password
smtp.EnableSsl = false;
smtp.Send(mail);
return View("Index", _objModelMail);
}
else
{
return View();
}
}
}
}
Index.cshtml
#model SendMail.Models.MailModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<fieldset>
<legend>Send Email</legend>
#using (Html.BeginForm())
{
#Html.ValidationSummary()
<p>From: </p>
<p>#Html.TextBoxFor(m=>m.From)</p>
<p>To: </p>
<p>#Html.TextBoxFor(m=>m.To)</p>
<p>Subject: </p>
<p>#Html.TextBoxFor(m=>m.Subject)</p>
<p>Body: </p>
<p>#Html.TextAreaFor(m=>m.Body)</p>
<input type ="submit" value ="Send" />
}
</fieldset>
UPDATE
How to setup SMTP server on IIS7
start->administrative tools->server manager, go to features, select "add features", tick "smtp server" (if it is not already installed), choose to install the required "remote server admin toos"
check to confirm that "Simple Mail Transfer Protocol (SMTP)" service is running, if so, we are good to go.
start->administrative tools>internet info services(iis) 6.0
make sure that SMTP virtual server/default smtp server is running, if not, right click, then choose "start"
in IIS7, go to website/virtual directory, double click "SMTP E-mail", Click on "Deliver e-mail to SMTP server", check the "Use localhost" checkmark
Why not try to use gmail for email sender? It's easy to use.
I always just build simple method
public void SendEmail()
{
MailMessage mail = new MailMessage("xxx#gmail.com", "sendTo", "mailSubject", "mailBody");
mail.From = new MailAddress("xxx#gmail.com", "nameEmail");
mail.IsBodyHtml = true; // necessary if you're using html email
NetworkCredential credential = new NetworkCredential("xxx#gmail.com", "xxxxx");
SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587);
smtp.EnableSsl = true;
smtp.UseDefaultCredentials = false;
smtp.Credentials = credential;
smtp.Send(mail);
}
Just use async/await if you want wait the email sent.

Categories