1

When user fills out subscribe form or contact form and the form is not valid it redirects to the form view

The forms are a partial form which are in the index page, possibly the issue but I'm not sure how to solve - it is a single page application with two actions, subscribe and contact.

How can I get it to stay on the same page and show the error.

Here is the subscribe Form (Contact is similar)

@model SubscribeViewModel

<!-- Subscribe Form -->
<form asp-controller="Home" asp-action="Subscribe" method="POST" enctype="multipart/form-data">
    <div class="form-row">
        <div>
            <input asp-for="Email" placeholder="Email address">
            <span asp-validation-for="Email" class="help-block text-danger"></span>
        </div>
        <div>
            <button type="submit">Subscribe</button>
        </div>
    </div>
</form>

Here is the Home Controller

//Subscribe
[HttpPost]
public IActionResult Subscribe(SubscribeViewModel vm)
{
    if (ModelState.IsValid)
    {
        _mailService.SubscribeEmail(vm.Email);

        return RedirectToAction("Index", "Home");
    }

    return - **What to do here??;**
}

// Send Mail
[HttpPost]
public IActionResult Contact(ContactViewModel vm)
{
    if (ModelState.IsValid)
    {
        _mailService.SendEmail(vm.Name, vm.Email, vm.Subject, vm.Message);

        return RedirectToAction("Index", "Home");
    }

    return - **And here?;**
}
ikaikastine
  • 601
  • 8
  • 22
rhino9
  • 51
  • 3
  • 9

5 Answers5

1

you need return View();

But also you'll want to add [ChildActionOnly] to your controller.

    //Subscribe
[ChildActionOnly]
[HttpPost]
public IActionResult Subscribe(SubscribeViewModel vm)
{
    if (ModelState.IsValid)
    {
        _mailService.SubscribeEmail(vm.Email);
        return RedirectToAction("Index", "Home");
    }

    return PartialView(vm)
}

ChildActionOnly

Mocolicious
  • 315
  • 1
  • 10
0

If the ViewModel is not valid, return the View that rendered the form originally, and pass the ViewModel you have received in the POST action.

This ViewModel will contain errors in ModelState.Errors which can be displayed by MVC, e.g. with @Html.ValidationSummary().

For this to work correctly, make sure that all properties of the ViewModel are posted back! If a property can not be changed by the User, render a hidden input for it so it will not get lost on the round trip.

[HttpPost]
public IActionResult Subscribe(SubscribeViewModel vm) {
     if (!ModelState.IsValid) {
         return PartialView("_SubscribeForm", vm);
     }

     // model is valid
     // ...
}
Georg Patscheider
  • 9,357
  • 1
  • 26
  • 36
  • The problem is it redirects me to a page with only the partial view and shows the errors there (eg Email is required). I need it it stay on the index page where I have Html.RenderPartial and show the errors there without redirecting – rhino9 Mar 15 '18 at 16:08
  • @sg9: *"return the View that rendered the form originally"* - as in the view for the whole page, not the partial view. – Chris Pratt Mar 15 '18 at 18:02
0

You just need to replace return - **What to do here??;** with this code.

return View("Your View name", vm);

This line populate all fields that are already entered by the user so you can identify the wrong values.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
Muhammad Asad
  • 1,772
  • 16
  • 23
0

I think ...

return View();

You simply need to return View() as per my under standing you write all action in index view controller so you write return View() is automatic return to index view, and also ModelState.IsValid is false so it show error messages so i think is enough to return View().

0

You could use ajax to post the data and report back errors (which is probably the cleanest solution, but this needs jQuery scripting and modifying your post actions). Too much to post as an answer, and you probably need something very specific.

Using the "Redirect" approach in your code means redirecting back to the Home Page but also transferring the ModelState errors as well (exporting the ModelState from the post action and importing it to the Home Page action), which can be done and is reasonably straightforward, but does need some more coding (and probably more research) - try searching for the "PRG pattern" to find coding examples.

As a starting point, there is a blog post by Kazi Manzur Rashid (see section 13. Use PRG Pattern for Data Modification) here which should get you started, but there are other useful posts out there as well.

The blog post describes how to use TempData and ActionFilters to import and export ModelStates (by decorating your actions with the attributes) and is very useful for redirects to avoid recreating ViewModels and for transferring ModelStates.

From what I see, there is no "one-liner quick fix", you just have to research and test this pattern, or go down the ajax/json route.

RickL
  • 3,318
  • 10
  • 38
  • 39
  • 1
    Correction: it doesn't need *jQuery*, but it does require *JavaScript*. In other words, it won't work if the end-user disables JavaScript in their browser, but you can use any library you like or none at all. – Chris Pratt Mar 15 '18 at 17:59
  • Completely agree - I was shortcutting and thinking $.ajax – RickL Mar 15 '18 at 18:02