Reputation: 374
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
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