NAGASREE
NAGASREE

Reputation: 374

InvalidOperationException : Asp.Net Core Model object usage in .cshtml

I have Upsert.cshtml assosciated with BooksController when I am trying to add book when loading the view it is getting the exception as mentioned below.

I am learning Asp.Net core as per my understanding Model means we can access the book object of controller and access the properties.Please help with this why I am not able to access Id using Model?

Upsert.cshtml

@{
    ViewData["Title"] = "Upsert";
}
@model BookListMVC.Models.Book

<br />
<h2 class="text-info">@(Model.Id != 0 ? "Edit" : "Create") Book</h2>
<br />
<div class="Border container" style="padding:30px;">
    <form method="post">
        @if (Model.Id != 0)
        {
            <input type="hidden" asp-for="Id" />
        }
        <div class="text-danger" asp-validation-summary="ModelOnly"></div>
        <div class="form-group row">
            <div class="form-group row">
                <div class="col-3">
                    <label asp-for="Name"></label>
                </div>
                <div class="col-7">
                    <input asp-for="Name" class="form-control" />
                </div>
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group row">
            <div class="form-group row">
                <div class="col-3">
                    <label asp-for="Author"></label>
                </div>
                <div class="col-7">
                    <input asp-for="Author" class="form-control" />
                </div>
                <span asp-validation-for="Author" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group row">
            <div class="form-group row">
                <div class="col-3">
                    <label asp-for="ISBN"></label>
                </div>
                <div class="col-7">
                    <input asp-for="ISBN" class="form-control" />
                </div>
                <span asp-validation-for="ISBN" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group row">
            <div class="col-3 offset-3">
                <button type="submit" value="Create" class="btn btn-primary form-control">
                    @(Model.Id != 0 ? "Update" : "Create")
                </button>
            </div>
            <div class="col-3">
                <a asp-page="Index" class="btn btn-success form-control">Back to List</a>
            </div>
        </div>
    </form>
</div>

@section Scripts{
    <partial name="_ValidationScriptsPartial" />
}




InvalidOperationException: The relative page path 'Index' can only be used while executing a Razor Page. Specify a root relative path with a leading '/' to generate a URL outside of a Razor Page. If you are using LinkGenerator then you must provide the current HttpContext to use relative pages.
Microsoft.AspNetCore.Mvc.Routing.UrlHelperBase.CalculatePageName(ActionContext context, RouteValueDictionary ambientValues, string pageName)
Microsoft.AspNetCore.Mvc.Routing.UrlHelperBase.NormalizeRouteValuesForPage(ActionContext context, string page, string handler, RouteValueDictionary values, RouteValueDictionary ambientValues)
Microsoft.AspNetCore.Mvc.UrlHelperExtensions.Page(IUrlHelper urlHelper, string pageName, string pageHandler, object values, string protocol, string host, string fragment)
Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGenerator.GeneratePageLink(ViewContext viewContext, string linkText, string pageName, string pageHandler, string protocol, string hostname, string fragment, object routeValues, object htmlAttributes)
Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper.Process(TagHelperContext context, TagHelperOutput output)
Microsoft.AspNetCore.Razor.TagHelpers.TagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.RunAsync(TagHelperExecutionContext executionContext)
AspNetCore.Views_Books_Upsert.<ExecuteAsync>b__21_0() in Upsert.cshtml
+
                    @(Model.Id != 0 ? "Update" : "Create")
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
Microsoft.AspNetCore.Mvc.TagHelpers.RenderAtEndOfFormTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.<RunAsync>g__Awaited|0_0(Task task, TagHelperExecutionContext executionContext, int i, int count)
AspNetCore.Views_Books_Upsert.ExecuteAsync() in Upsert.cshtml
+
<h2 class="text-info">@(Model.Id != 0 ? "Edit" : "Create") Book</h2>
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result)
Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)

Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Upvotes: 0

Views: 794

Answers (1)

Rena
Rena

Reputation: 36645

The error message means you use the wrong tag helper asp-page,change like below:

<a asp-action="Index" class="btn btn-success form-control">Back to List</a>

The whole demo like below:

Model:

public class Book
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Index.cshtml:

@model IEnumerable<Book>

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>

Create.cshtml:

@{
    ViewData["Title"] = "Upsert";
}
@model Book

<br />
<h2 class="text-info">@(Model.Id != 0 ? "Edit" : "Create") Book</h2>
<br />
<div class="Border container" style="padding:30px;">
    <form method="post">
        @if (Model.Id != 0)
        {
            <input type="hidden" asp-for="Id" />
        }
        <div class="text-danger" asp-validation-summary="ModelOnly"></div>
        <div class="form-group row">
            <div class="form-group row">
                <div class="col-3">
                    <label asp-for="Name"></label>
                </div>
                <div class="col-7">
                    <input asp-for="Name" class="form-control" />
                </div>
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
        </div>

        <div class="form-group row">
            <div class="col-3 offset-3">
                <button type="submit" value="Create" class="btn btn-primary form-control">
                    @(Model.Id != 0 ? "Update" : "Create")
                </button>
            </div>
            <div class="col-3">
                <a asp-action="Index" class="btn btn-success form-control">Back to List</a>
            </div>
        </div>
    </form>
</div>

@section Scripts{
    <partial name="_ValidationScriptsPartial" />
}

Controller:

public class BooksController : Controller
{
    private readonly MyDbContext _context;

    public BooksController(MyDbContext context)
    {
        _context = context;
    }
    // GET: Books
    public async Task<IActionResult> Index()
    {
        return View(await _context.Book.ToListAsync());
    }

    // GET: Books/Create
    public IActionResult Create()
    {
        var model = new Book() { Id = 0 };
        return View(model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("Id,Name")] Book book)
    {
        if (ModelState.IsValid)
        {
            _context.Add(book);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(book);
    }

    public async Task<IActionResult> Edit(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var book = await _context.Book.FindAsync(id);
        if (book == null)
        {
            return NotFound();
        }
        return View("Create",book);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(int id, [Bind("Id,Name")] Book book)
    {
        if (id != book.Id)
        {
            return NotFound();
        }

        if (ModelState.IsValid)
        {  
            _context.Update(book);
            await _context.SaveChangesAsync();                              
            return RedirectToAction(nameof(Index));
        }
        return View("Create",book);
    }
}

Upvotes: 1

Related Questions