1

I'm trying to post a message after a contact form, indicating to the user that their message has been sent after they click the submit button. I don't want to redirect to a different page or to return a different view inside my HTTP Post action method. How do I do something like that in ASP.NET MVC framework?

Below is my code sample:

@*contactus.cshtml*@
            @model MySite.Models.ContactModel
            @using (Html.BeginForm())
            {
                <div class="col-md-6">
                    <div class="form-group">
                        @Html.TextBoxFor(model => model.Name})
                        <p>@Html.ValidationMessageFor(model => model.Name)</p>
                    </div>
                    <div class="form-group">
                        @Html.TextBoxFor(model => model.Email)
                        <p>@Html.ValidationMessageFor(model => model.Email)</p>
                    </div>
                    <div class="form-group">
                        @Html.TextAreaFor(model => model.Message)
                        <p>@Html.ValidationMessageFor(model => model.Message)</p>
                    </div>

                    <div class="col-lg-12">
                        <button type="submit">Send Message</button>
                    </div>
                </div>
            }

@*ContactModel.cs*@
public class ContactModel
{
    [Required(ErrorMessage = "* Please enter your name.")]
    [StringLength(100, MinimumLength=3, ErrorMessage="* Please enter your full name.")]
    public string Name { get; set; }

    [Required]
    [EmailAddress(ErrorMessage="* Not a valid email address.")]
    public string Email { get; set; }

    [Required]
    public string Message { get; set; }
}

I only have a contact us form right now on my home/index page, and I don't want to redirect it to any other pages. I would like to display a message right below the Send Message button, but I'm not sure how to go about it using the action method below:

@*HomeController.cs*@
    public ActionResult Index(ContactModel model)
    {
        if (ModelState.IsValid)
        {
            // this is my helper library, for brevity, I'm not copying it.
            EmailHelper emailService = new EmailHelper(); 
            bool success = emailService.SendEmail(model.Name, model.Email, model.Message);
            return Content(success ? "success" : "no...something went wrong :(");
        } else {
            return View(model);
        }
    }

Right now this controller will return the string inside Content which replaces my entire page, and I would like the string to be returned below my contact form. Also, I have two sections on the same html page with Contact Form as the second one, when I return View(model), it automatically redirects to the first section, which isn't ideal... How do I tell the controller to only redirect it to the second section after the POST method? In addition, I feel like it would be more efficient if it didn't return the whole page... so is there a way to only return a Message string to the div?

Lula la
  • 13
  • 7

2 Answers2

0

You can place a hidden div on the page which will contain the message.

Then when your form has been submitted, capture the click event for your button, and use that to display the hidden message.

Let me know if you need a code example. Posting your form would help us answer you more specifically.

wicker95
  • 131
  • 1
  • 10
  • Thank you so much for the prompt response! I will add a code sample right now. Since I'm using ASP.NET, is there a way to capture the click event using C# or do I have to use JQuery? – Lula la Jun 23 '15 at 16:30
  • You **can** capture it in C#, but since you're in MVC, you'd be much better served to use either Javascript or jQuery. Anything you can do to avoid a postback for such a simple piece of functionality will speed up the page, as well. Of course, you're likely going to do a postback to submit the form, but keeping the message to the user on that page will still make it much faster for the user. – wicker95 Jun 23 '15 at 17:35
  • That makes sense. Thank you. I will use JQuery to capture the button click. Will I still be able to send my form in the HomeController? – Lula la Jun 23 '15 at 17:43
  • You sure can. Let me know if you need help with that code. – wicker95 Jun 23 '15 at 20:14
  • Yes, please! Some sample code for that would help me so much! I've done some research and written a few scripts, none of which worked. I can get AJAX to call my controller, but no matter what the controller returns, the returned value is always on a new page instead of the div on my current page... Thank you so much in advance!!! – Lula la Jun 23 '15 at 20:38
  • Can you post your ajax call? It sounds like you're doing a full post to the controller, which then returns an ActionResult. – wicker95 Jun 24 '15 at 12:20
  • I got it working finally! I was doing a full post for some reason, but now it's running well. Thank you so much for your help! – Lula la Jun 25 '15 at 21:24
  • I wanted to upvote your comment, but it looks like I don't have enough reputation to do that since I'm a newbie. Again, thank you thank you!! – Lula la Jun 25 '15 at 21:26
0

To only show the success message if the form is successfully sent, I would recommend setting a value in the ViewBag in the POST action of the controller and then returning that same page if you want to still have the same page showing. On the View itself, you could then place an If statement to test if the ViewBag variable contains a value and if so, display the message.

Controller:

[HttpPost]
public ActionResult YourAction(YourModel m)
{
    //Do stuff to send the contact form
    ...
    if(error)
    {
        ViewBag.Message = "There was a problem sending the form.";
    }
    else
    {
        ViewBag.Message = "The form was sent successfully!";
    }
    return View(m);
}

View:

@if(ViewBag.Message != null)
{
    <div>@ViewBag.Message</div>
}

This lets you check if the form was posted successfully on the server before telling the user the result and will only display a message if ViewBag.Message has been set. Note that you can have as many ViewBag variables as you want and can name them whatever you want... just remember which one you use in which place.

EDIT:

Following the comments, this could also be done using an AJAX call. I'll use the jQuery .post() method for simplicity sake.

In Script:

<script>
    $(document).on('click', "#buttonId", function() {
        var nameText = $("#IdOfNameField").val();
        var emailText = $("#IdOfEmailField").val();
        var messageText = $("#IdOfMessageField").val();
        $.post('@Url.Content("~/Controller/AJAXPostContactForm")',//the url to post to
            {name: nameText, email: emailText, message: messageText }, //these are values to be sent to the action
            function(){ //this is the success function
                $("#successMessage").val("Form posted successfully.");
            }
        )
        .fail(function() {//failure function
            alert("Something went wrong.");
        });
    }
</script>

Controller:

public void AJAXPostContactForm(string name, string email, string message)
{
    try
    {
        //do stuff with the information passed into the action
    }
    catch(exception e)
    {
        //Handle errors. If error thrown, Ajax should hit fail block in script
    }
    finally
    {
        //do any cleanup actions
    }
}

View:

<div id="successMessage"></div>

I have not tested this code but it should theoretically work. On a specific button click, it will get the values from the form fields, post those values to a specialized ActionResult in the controller, and then return a message about what happened.

  • Ohh nice usage of ViewBag! Thank you! My other concern is that since I have two sections on the same page with Contact form as the second one, when I return View(model), it automatically redirects to the first section, which isn't ideal... How do I tell the controller to only redirect it to the second section? Also, I feel like it would be more efficient if it didn't return the whole page...Thank you again so so much for the fast response!! – Lula la Jun 23 '15 at 17:06
  • You could use an AJAX call to post the form instead. You would still have to have the form processed on the server, but the page itself wouldn't have to reload. This would probably also solve the problem of it going back to the top of the page since the page wouldn't reload. However, this would be quite a bit more complicated to implement than just using the ViewBag to send text from the controller to the view. – IamzombieGrrArgh Jun 23 '15 at 17:22
  • I see... Thank you so much. I think I will go with the AJAX call. Will I still be able to process the form in my controller? – Lula la Jun 23 '15 at 17:42
  • You can still process in the controller. I added a quick and dirty example of how an AJAX post could be used to do this. Note that there are a couple of different ways to use AJAX... I like to use the jQuery API because it simplifies the process a bit so that is what I used here. They all essentially do the same thing, just with different syntax. – IamzombieGrrArgh Jun 23 '15 at 18:11
  • Thanks for the example. I followed it through but what I got was a page with the message json object instead of my contact form page. Are you using Ajax.BeginForm? – Lula la Jun 23 '15 at 18:28
  • I am using Html.BeginForm(null, null, FormMethod.Post). I may have lead you down the wrong path there a bit... I think that I was thinking of a getJSON() AJAX call. Try the edits that I made which doesn't return anything from the actionresult and sets the text based on the success and fail functions in the .post() method. – IamzombieGrrArgh Jun 23 '15 at 18:47
  • Hmm..but the latest edits do not allow controller to give us feedback indicating whether or not the message was sent successfully. I tested the code, but after clicking the button, I end up with a blank page even though I set the return type of the controller to null... – Lula la Jun 23 '15 at 19:02
  • If you return null, the page will be empty (null). I guess that I am just too used to using ActionResult as a return type that I put that in there... you really shouldn't need anything returned for something like this so you could make that void. All that you should have to do is place a try/catch block in your AJAX controller. If the function finishes successfully, the success function in the script should run. If an error is thrown, the fail function should run. – IamzombieGrrArgh Jun 24 '15 at 14:02
  • Thank you so much! I have the problem figured out now. :) I wanted to upvote your comment, but it looks like I don't have enough reputation to do that since I'm a newbie. Again, thank you thank you!! – Lula la Jun 25 '15 at 21:24