2

I am trying to figure out what is the best way to show a generic error message that can be shown in all of the pages in my app. The error view should be shown when a form POST request is executed.

To make the error view available everywhere I've put it in the _Layout.cshtml but I am not quite sure how show it when I submit a POST request from my form.

Note: the solution should not force the page to refresh (i.e. should be asynchronous).

Right now I am using TempData to store and show the message

This is my _Layout.cshtml

<!DOCTYPE html>
...
<body>
@if (TempData["SystemError"] != null)
{
    <div>@TempData["SystemError"]</div>
}

@RenderSection("BodyFill", false)
@RenderBody()
...
@RenderSection("Scripts", required: false)
</body>
</html>

This is my controller action:

[HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult ShareWorkbook(string emails, string title, string id, string queryBuilderId)
    {
        var emailStrArr = Regex.Split(emails, Constants.SplitPattern).ToList();

        var workbookShareModel = new WorkbookShareModel
        {
            Id = id,
            QueryBuilderId = queryBuilderId,
            Title = title,
            Emails = emailStrArr
        };

        // check to see if the 'WorkbookShareModel' is valid (takes into account its property DataAnnotation)
        if (TryValidateModel(workbookShareModel))
        {
            try
            {
                ShareWorkbook(workbookShareModel);
            }
            catch (Exception e)
            {
                //Todo -- Exception handling
                TempData["SystemError"] = Res.System_Error_Message;
            }
        }

        // return no content to avoid page refresh
        return NoContent();
    }

That is the form (it's in a partial view that is loaded into the index.cshtml)

@using DNAAnalysisCore.Resources
@model DNAAnalysisCore.Models.WorkbookShareModel
@* Partial view that contains the 'Share Workbook dialog' modal *@

<!-- Modal -->
<div onclick="activateShareButtons()" class="modal fade" id="shareFormModal" role="dialog">
    <div class="modal-dialog modal-md">
        <!-- Modal content-->
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title">Share Workbook - @Model.Title</h4>

            </div>

            @using (Html.BeginForm("ShareWorkbook", "Home", FormMethod.Post, new { @id = "partialform" }))
            {
                <div class="modal-body">

                ...

                <div class="modal-footer">
                    <button onclick="hideDialog()" type="submit" class="btn btn-primary">Share</button>
                    <button onclick="activateShareButtons()" id="btnCancelDialog" type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
                </div>
            }

        </div>
    </div>
</div>
Georgi Koemdzhiev
  • 11,421
  • 18
  • 62
  • 126
  • You can achieve by JQuery Ajax. Assign an ID attribute to the error message div and set the message using JQuery $("#divid").html("Error message") – Golda May 08 '19 at 11:53
  • @Golda Thank you for your comment. However, I am not sure how to show the message when there is an exception on the controller's action method – Georgi Koemdzhiev May 08 '19 at 12:36

2 Answers2

1

Create a div in _Layout.cshtml

<div id="messageDiv"></div>

Button in the partial view with ValidateButton() function on onclick event

<button onclick="ValidateButton()" id="btnCancelDialog" type="button" class="btn btn-default">Validate</button>

JQuery

function ValidateButton() {
   // If you have any parameter
    var obj ={
        parm: "1"
    };

    $.ajax({
        url: '/Home/ValidationProcess',
        contentType: 'application/json; charset=utf-8',
        type: 'POST',
        data: JSON.stringify(obj),
        cache: false,
        success: function (result) {
            $("#messageDiv").html(result);
        },
        error: function (xhr, status, error) {
            alert("Error");
        }
    });
}

Controller

public string ValidationProcess(string parm)
{
    // Do something

    return "Message";
}

Don't forget to add JQuery library

Golda
  • 3,823
  • 10
  • 34
  • 67
  • Thank you for your answer, Golda. I managed to come up with another solution that does not use IQuery and it's a bit simpler in my case. I will post it below. – Georgi Koemdzhiev May 08 '19 at 13:55
1

I managed to find a solution using the unobtrusive Ajax html (this stack overflow question helped me - link). I converted my original Html.BeginForm (synchronous) to asyncronous call that refreshes a div when the request is executed:

<form id = "partialform" asp-action="ShareWorkbook" asp-controller="Home" method="post" data-ajax="true" data-ajax-update="divEmp">
<div class="modal-body">
    ...
    <div class="modal-footer">
        <button onclick="hideDialog()" type="submit" class="btn btn-primary">Share</button>
        <button onclick="activateShareButtons()" id="btnCancelDialog" type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
    </div>
</div>
</form>

_Layout.cshtml:

...
<body>
<div id="divEmp">
    @if (TempData["error"] != null)
    {
        <p>@TempData["error"]</p>
    }
</div>
@RenderSection("BodyFill", false)
@RenderBody()
...

Controller:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ShareWorkbook(string emails, string title, string id, string queryBuilderId)
{
    ...

    TempData["error"] = "TEST ERROR MESSAGE";
    // return no content to avoid page refresh
    return NoContent();
}
Georgi Koemdzhiev
  • 11,421
  • 18
  • 62
  • 126