3

I'm developing a MVC 5 app with the SweetAlert 2 plugin.

My Goal: When an error occurs anywhere in my app I'd like to display a (centralized, sweetalert) modal dialog with a title/message.

I created a PartialView called "_ModalError" and referenced this in the bottom of my main, shared "_Layout" view. Basically so this partial view will be enabled for every page.

I then created a simple Error class...

namespace MyApp.Models
{
    public class MyError
    {
        public string ErrorTitle { get; set; }
        public string ErrorMessage { get; set; }
    }
}

I was thinking that, whenever I get an error, I would instantiate a new MyError object, set the appropriate ErrorTitle and ErrorMessage properties, then set ViewBag.Error to this MyError object.

private MyError err = new MyError();
err.ErrorMessage = "Your information was not valid. Please re-check everything.";
err.ErrorTitle = "Error!";
ViewBag.Error = err;

Then, in javascript, whenever the _ModalError (the page) loads, it would look to see if ViewBag.Error exists. If so, an error occurred, so display it. Here's what I have so far....

<script>
    $(function() {
        if (@ViewBag.Error != null) {
            swal(
                @ViewBag.Error.ErrorTitle, 
                @ViewBag.Error.ErrorMessage,
                'error'
            );
    };
</script>

The problem is that when the page first loads I get this error when it hits the viewbag code...

Cannot perform runtime binding on a null reference.

I'm trying to access ViewBag but apparently it doesn't exist at first, which makes sense. But, checking to see if it's null isn't really working. Do you know why this is? Any suggestions? Is this a faulty, crazy, or over-kill solution?

******** SOLUTION ********

Here's the solution. Thanks to Stephen Muecke (below) for the Json.Encode advice! I hope this is helpful to someone else!

<script>
$(function() {
    var error = @Html.Raw(Json.Encode(ViewBag.Error));
    if (error != null) {
        swal(
            error.ErrorTitle,
            error.ErrorMessage,
            'error'
        );
    }
})

WebDevGuy2
  • 1,159
  • 1
  • 19
  • 40
  • http://stackoverflow.com/questions/8640927/checking-to-see-if-viewbag-has-a-property-or-not-to-conditionally-inject-javasc – Igor Mar 01 '17 at 02:57
  • you need to wrap `@ViewBag.Error.ErrorTitle` and `@ViewBag.Error.ErrorMessage` in quotes – Igor Mar 01 '17 at 03:01

1 Answers1

2

The issue is that razor code is parsed on the server before its sent to the view, so @ViewBag.Error.ErrorTitle, and @ViewBag.Error.ErrorMessage are evaluated on the server, and if @ViewBag.Error is null, the exception is throw because you cannot access a property of a null object. (it does not stop evaluating it just because its in a javascript if statement - that is client side code and does not even exist at that point)

Instead, assign the Error object to a javascript object, and then test it in you if block

$(function() {
    // Assign to a javascript variable
    var error = @Html.Raw(Json.Encode(ViewBag.Error))
    if (!error) {
        swal(
            error.ErrorTitle, 
            error.ErrorMessage,
            'error'
        );
    }
}

You should also consider using a base view model containing your Error object rather than passing it around in a ViewBag property.

  • He needs first to determine if `ViewBag` has `Error` property. – Igor Mar 01 '17 at 03:18
  • @Igor. That is exactly what `if (!error) {` does :) –  Mar 01 '17 at 03:20
  • Hm, ok. I was under the impression that accessing non-existing property of a dynamic object is a no-no. – Igor Mar 01 '17 at 03:22
  • @Igor, Its not accessing _a non-existing property of a dynamic object_. The first line of code evaluates to either `null` (if `ViewBag.Error` has not been assigned) or to `{ ErrorTitle: 'Error!', ErrorMessage: 'Your information was .... ' }` if it has. Its then javascript that is accessing the values of the properties (not razor) –  Mar 01 '17 at 03:24
  • @StephenMuecke perfect! Thanks! – WebDevGuy2 Mar 01 '17 at 04:33