0

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)
0

1 Answer 1

1

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);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.