简体   繁体   中英

C# Razor View passing null object to JavaScript

Here's the rundown. Users can view a razor page both anonymously and logged in. If they are logged in, they get certain features. In my controller, I have a boolean isAnonymous which I set to true or false depending on if there's a signed in user or not. I pass isAnonymous to my view model which gets sent to the razor page.

In the razor page, I have a javascript script tag which needs to retrieve that boolean value and, if isAnonymous is false (meaning someone is signed in), fire off one of two ajax calls to the server.

The first thing I do in my script tag is get the isAnonymous value and convert it to a JavaScript boolean with this:

var isAnonymous = @Json.Encode(Model.IsAnonymous);

after console logging, this appears to return correctly.

Then i put in my if statement. The summary here is if the user is not logged in, none of these functions nested inside the if statement should fire, because they take an ApplicationUser as part of the model. If there is no signed in user, Model.User is null and throws a Null Reference Exception . I thought putting my ajax calls inside the if statement would guard against the exception, but the the logic seems to be blowing right through the if (isAnonymous == false) and hitting those functions despite the logic. Any thoughts as to why this is happening? When isAnonymous is true, I can't have the functions fire.

if (isAnonymous == false) {
    if ($('.bookmark-btn').hasClass('bookmark-story-btn')) {
        addBookmark();
    } else {
        removeBookmark();
    }

    function addBookmark() {
    //bookmark a story btn click event
    $('.bookmark-story-btn').on('click', function () {

        var storyid;

        //the storyid should come as a string - 
        //try to parse it as an int for the controller
        if (!isNaN($(this).attr('storyid'))) {

            storyid = parseInt($(this).attr('storyid'))
            //verify successful conversion from string to int before ajax call
            if (typeof (storyid) == 'number') {
                var userid = $(this).attr('userId')

                var newBookmark = {
                                    UserId: userid,
                                    StoryId: storyid,
                                  };

                $.ajax({
                    url: "/api/bookmark/new",
                    method: "POST",
                    data: newBookmark,
                    success: function (data) {
                            //remove the save bookmark btn and dynamically add
                            //the remove bookmark btn so 
                            //the page doesn't require a refresh
                            $('.bookmark-story-btn').remove();
                            $('.bookmark-btn-group').append("<button bookmarkId='" 
                                + data.Id 
                                + "' userId=@Model.User.Id storyId=@Model.StoryId"
                                +" class='btn remove-bookmark-btn bookmark-btn'>"
                                +"<i class='fas fa-2x fa-bookmark'></i></button>")
                            removeBookmark();
                        },
                    error: function (error) {
                            $('.page-alert').css('visibility', 'visible')
                                .html("Whoops. Something went wrong."
                                        +" Adding the bookmark failed.")
                            //automatically close the alert-danger div 
                            //after 2 seconds
                            setTimeout(function () {
                                $('.page-alert').css('visibility', 'hidden')
                            }, 3000);
                        }
                    });
                }
            }
        });
    }

    function removeBookmark() {
        //remove a bookmark click event
        $('.remove-bookmark-btn').on('click', function () {

            if (!isNaN($(this).attr('bookmarkid'))) {
                bookmarkid = parseInt($(this).attr('bookmarkid'))
                //verify successful conversion from string to int before ajax call
                if (typeof (bookmarkid) == 'number') {

                    //call the ajax
                    $.ajax({
                        url: "/api/bookmark/" + bookmarkid,
                        method: "DELETE",
                        success: function (data) {
                            //show-hide the appropriate icons
                            $('.remove-bookmark-btn').remove();
                            $('.bookmark-btn-group').append("<button userId=@Model.User.Id"
                                +" storyId=@Model.StoryId class='btn bookmark-story-btn"
                                +" bookmark-btn'><i class='far fa-2x fa-bookmark'>"
                                +"</i></button>")
                            addBookmark();
                        },
                        error: function (error) {
                            $('.page-alert').css('visibility', 'visible')
                                    .html("Whoops. Something went wrong here."
                                        +" Removing the bookmark didn't work.")
                            //automatically close the alert-danger div 
                            //after 2 seconds
                            setTimeout(function () {
                                $('.page-alert').css('visibility', 'hidden')
                            }, 3000);
                        }
                    })
                }
            }
        })
    }
} 

You can use Request.IsAuthenticated in both the Razor view:

@if(Request.IsAuthenticated)
{
    <script>
        ' your authenticated client side script here
    </script>
}

And then check again server side when posting in your controller for example:

    public ActionResult Index()
    {
        if(Request.IsAuthenticated)
        {
            //server logic here
        }
    }

Better still if you decorate the method with the AuthoriseAttribute the user will get an 403 Unauthorized.

You can then do something similar server side for the UserId:

    [Authorize]
    public ActionResult Index()
    {
        var userId = User.Identity.Name;
    }

Then you don't even need to pass the UserId about. This is all based on using the common Identity practices:

https://docs.microsoft.com/en-us/aspnet/identity/overview/getting-started/introduction-to-aspnet-identity

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM