Ad

Can I Use ViewData As A State Management Device In ASP.NET MVC?

- 1 answer

I'm building a basic blogging site using ASP.NET MVC using Microsoft Identity. I want to allow the author of a post to have delete privileges and everyone else should not. What I'm trying to do is have a ViewData["isAuthor"] variable manipulated in the controller and passed down to the returned view based on whether or not they pass a check.

I have no errors and in my head this is working but the variable is not being reevaluated in the controller for some reason.

Here is my razor page:

@model securitypractice.Models.Article

@{
    ViewData["Title"] = "Delete";
    ViewData["Deletable"] = true;
}

<h1>Delete</h1>

@if((bool)ViewData["Deletable"]! == true)
{
    <h3>Are you sure you want to delete this post?</h3>
<div>
    <hr />
    <dl class="row">
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.Title)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.Title)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.ArticleBody)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.ArticleBody)
        </dd>
    </dl>
    
    <form asp-action="Delete">
        <input type="hidden" asp-for="Id" />
        <input type="submit" value="Delete" class="btn btn-danger" /> |
        <a asp-action="Index">Back to List</a>
    </form>
    </div>
} else if((bool)ViewData["Deletable"]! == false)
{
    <div class="row">
        <div class="col-sm-8">
            <h2>Only the post author or moderator has the ability to delete a post.</h2>
             <a asp-action="Index">Back to List</a>
        </div>
    </div>
}

And here is my controller:

// GET: Articles/Delete/5
    [Authorize]
    public async Task<IActionResult> Delete(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var article = await _context.Articles
                                    .FirstOrDefaultAsync(m => m.Id == id);

        if (article == null)
        {
            return NotFound();
        }

        ViewData["Deletable"] = (User.Identity.Name == article.Author) ? true : false;

        return View(article);
    }
Ad

Answer

Remove the line ViewData["Deletable"] = true; from the top of your view.

That actually assigns the value to true and will overwrite the value sent from the controller.


Aside: The reason the title is set within the view is because the value ViewData["Title"] is used within the _Layout.cshtml template to give the page an appropriate title (although, it could be assigned in the controller instead).

Ad
source: stackoverflow.com
Ad