Change button label text dynamically in razor pages - c#

I am using Razor Pages in my ASP.NET Core web application.
I would like to change the button text from code-behind. Even if i add runat="server" in Html markup and I can't access the button in *.cshtml.cs file.
Also, I can not use <asp:button> in razor pages. Is there any way to do without using the javascript approach?
<input type="submit" value="Create" class="btn btn-primary"/>
MyPage.cshtml.cs
public IActionResult OnGet(Guid id)
{
if(id == Guid.Empty) //Make button create
else // make it update
}

Razor Pages in .net core are quite a bit different than classic aspx pages. There are a number of good intro articles out there in this one from MS. Using your question and some sample code from that article this what the page might look like.
The cshtml file might look like:
#page
#using RazorPagesIntro.Pages
#model IndexModel2
<h2>Separate page model</h2>
<p>
<input type="submit" value="#Model.Label" class="btn btn-primary"/>
</p>
The cshtml.cs page model:
using Microsoft.AspNetCore.Mvc.RazorPages;
using System;
namespace RazorPagesIntro.Pages
{
public class IndexModel2 : PageModel
{
[BindProperty]
public string Label { get; set; }
public void OnGet()
{
if (id == Guid.Empty) {
Label = "Create";
} else {
Label = "Update";
}
}
}
}

Related

Not returning a list of data into index view in ASP.NET Core MVC

I was programming my own website using ASP.NET Core MVC and following one of the video tutorials I wanted to iterate data which is populated from my database to the view. Here are the codes:
Repository
public class ChoreBearRepository : IChoreBearRepo
{
private readonly DatabaseContext _context;
public ChoreBearRepository(DatabaseContext context)
{
_context = context;
}
/*
This methods returns all categories from the database using the background thread.
*/
public async Task<List<CategoryofTask>> GetAllCategories()
{
return await _context.categoryOfTasks
.Select(category => new CategoryofTask(){
CategoryName = category.CategoryName,
CategoryDesc = category.CategoryDesc,
CategoryID = category.CategoryID,
CategoryImageURL = category.CategoryImageURL,
CategoryRate = category.CategoryRate
}).ToListAsync();
}
}
Controller:
public class HomeController: Controller
{
private readonly IChoreBearRepo _repository;
public HomeController(IChoreBearRepo repository)
{
_repository = repository;
}
// public IActionResult Index()
// {
// return View();
// }
[HttpGet]
public async Task<IActionResult> Index()
{
var data = await _repository.GetAllCategories();
return View(data);
}
}
Index.cshtml
#page
#model IEnumerable<ChoreBear_Website.Models.CategoryofTask>
<div class="row">
#foreach (var category in Model)
{
<partial name="Categories" model=#Model/>
}
</div>
Partial View (Categories.cshtml)
#model CategoryofTask
<div class="card" style="width: 18rem;">
<img class="card-img-top" src="#Model.CategoryImageURL" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">#Model.CategoryName</h5>
<p class="card-text">#Model.CategoryDesc</p>
Go somewhere
</div>
</div>
The list contains data from the database but the website project returns me an error which is :
NullReferenceException: Object reference not set to an instance of an
object. MyApp.Namespace.Home.Views_Home_Index.get_Model()
I do know that the list is null which is why I would like to know where should I initialise the list. I followed the code example from the video tutorial.
PS: I followed this video tutorial Get List of Data from Database
Your code looks OK to retrieve a list and return it to a VIEW "Index", even if that list is empty because there are no records in the database.
However, there are two problems. One your Index.cshtml has the "#page" directive which means it is now a Razor Page instead of a View and expects to find the model in the page behind Index.cshtml.cs or in a #code section on the same page. This is the source of your error.
Additionally, in the following, your are passing the IEnumerable as the model to the partial view, which is expecting an individual CategoryOfTask ...
#model IEnumerable<ChoreBear_Website.Models.CategoryofTask>
<div class="row">
#foreach (var category in Model)
{
<partial name="Categories" model=#Model/>
}
</div>
Try changing ...
<partial name="Categories" model=#Model/>
to ...
<partial name="Categories" model=#category/>
To understand differences between Razor Views and Pages, see this link:
https://learn.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-5.0&tabs=visual-studio
The preceding code looks a lot like a Razor view file used in an
ASP.NET Core app with controllers and views. What makes it different
is the #page directive. #page makes the file into an MVC action -
which means that it handles requests directly, without going through a
controller. #page must be the first Razor directive on a page. #page
affects the behavior of other Razor constructs. Razor Pages file names
have a .cshtml suffix.

Multiple submit actions with multiple submit buttons in asp net core razor page

I have a razor page with a form and multiple submit buttons. with each button I want to start a different Post action in my codebehind file. so this is in my cshtml page:
<form class="form" method="post" >
<input type="submit" value="Test1" formaction="Button1" />
<input type="submit" value="Test2" formaction="Button2" />
</form>
and this in my cshtml.cs file:
[HttpPost]
public IActionResult Button1(IFormCollection data)
{
//my code
}
[HttpPost]
public IActionResult Button2(IFormCollection data)
{
//my code
}
Unfortunately, this is not working. when I submit I get a 404 error:
This localhost page can’t be found No webpage was found for the web address: https://localhost:44366/Mutations/Button1
HTTP ERROR 404
The correct URL should be: https://localhost:44366/Mutations/Test
What am I doing wrong?
Because you are a project in Razor, the routing rules in Razor are different from MVC projects, you can change your code as follows:
Your cshtml.cs file:
public IActionResult OnPostButton1(IFormCollection data)
{
//...
}
public IActionResult OnPostButton2(IFormCollection data)
{
//...
}
Your cshtml page:
<form class="form" method="post">
<input type="submit" value="Test1" asp-page-handler="Button1"/>
<input type="submit" value="Test2" asp-page-handler="Button2"/>
</form>
Result:
You must assign different routes (that match your formaction) to both actions:
[HttpPost("button1")]
public IActionResult Button1(IFormCollection data)
{
//my code
}
[HttpPost("button2")]
public IActionResult Button2(IFormCollection data)
{
//my code
}

return View(model: MyModel); equivalent in ASP.Net Core Razor Pages

I expected to see something like return Page(model: MyModel); in ASP Razor Pages. instead the Page(); has no parameter.
So I can return Pages which does not have PageModel class.
I cant use TempData as MyModel is a complex type.
How do I get the same functionality we have with ASP MVC return View(model: MyModel);
Please, The question is not for all MVC developers but experienced ASP.Net Core Razor Page developers.
Thank you.
Ok here is an example from a simple Restaurant app.
As you can see the Restaurant object is a property inside the DetailModel. Once i set it inside the OnGet() method. I am able to access its data inside my Razor Page View.
public class DetailModel : PageModel
{
private readonly IRestaurantData restaurantData;
[TempData]
public string Message { get; set; }
public Restaurant Restaurant { get; set; }
public DetailModel(IRestaurantData restaurantData)
{
this.restaurantData = restaurantData;
}
public IActionResult OnGet(int restaurantId)
{
Restaurant = restaurantData.GetById(restaurantId);
if(Restaurant == null)
{
return RedirectToPage("./NotFound");
}
return Page();
}
}
and the view from the page.
#page "{restaurantId:int}"
#model MyProject.Pages.Restaurants.DetailModel
#{
ViewData["Title"] = "Detail";
}
<h2>#Model.Restaurant.Name</h2>
<div>
Id: #Model.Restaurant.Id
</div>
<div>
Location: #Model.Restaurant.Location
</div>
<div>
Cuisine: #Model.Restaurant.Cuisine
</div>
#if(Model.Message != null)
{
<div class="alert alert-info">#Model.Message</div>
}
<a asp-page="./List" class="btn btn-default">All Restaurants</a>
Really Razor pages work as one so you do not have to return the Model. You just bind it and you have access inside the page.
Does this makes sense?
Please also read the DOCS for more information: https://learn.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-3.1&tabs=visual-studio

How do I start a ASP.NET Core Razor application from scratch

I am trying to get a clear mental picture on how an ASP.NET Core Razor application works. So I created an empty project template and tried to recreate the original "Razor Pages Template". After learning a lot of things the hard way, It seems just impossible to get a submit button to work. Take a look at some of my code:
Create.cshtml
<p>#Model.Message</p>
<h2>Create a new customer.</h2>
<p>Enter you name.</p>
<div asp-validation-summary="All"></div>
<form method="post">
<div>Name: <input asp-for="Customer.Name" /> </div>
<input type="submit" />
</form>
Create.cshtml.cs
public class CreateModel : PageModel
{
public AppDbContext DB { get; }
[BindProperty]
public string Message { get; set; }
public CreateModel(AppDbContext db)
{
DB = db;
}
[BindProperty]
public Customer Customer { get; set; }
public void OnGet()
{
Message = "This is from the get method";
}
public IActionResult OnPost()
{
Message = "This is from the post method";
if (!ModelState.IsValid)
return Page();
DB.Customers.Add(Customer);
DB.SaveChanges();
return RedirectToPage("/Index");
}
}
Most of that code is from (MSDN Docs), It works if I create a Razor Template and then delete, and arrange everything to my taste. But when I create a project without the template, the button brings up a 404 error. Also, commands like asp-validation-summary are not made bold like they normally are when I'm using the razor pages template.
If you want to use Razor pages, you have to include a #page directive on the top of your page, otherwise it returns 404 Not Found.
#page
#model CreateModel
<p>#Model.Message</p>
<h2>Create a new customer.</h2>
...

Showing testbox text in a label after clicking submit button in MVC3 Razor

I have a testbox control and a submit button control in my form together with a label control. When i type in some text in my testbox control and click the button control i am not being able to display that text in my label control. Kindly help.
As i am new to MVC and am learning the basics it will be very helpful for me if you can kindly give me the full coding.
You can also kindly mail me the codings. Thanks in advance.
My codes are as follows:
Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace TestMVCProj.Models
{
public class TestPost
{
public string name {get; set;}
}
}
Controller
using TestMVCProj.Models
public ActionResult TestPost(TestPost tp)
{
return View();
}
View
#model TestMVCProj.Models.TestPost
#{
ViewBag.Title ="TestPost";
}
#using (Html.BeginForm())
{
#Html.TestBoxFor (x => x.name)
<input type="submit" />
}
Your Name is <%= Model.name %>
I think you need to pass the model to View when post.
public ActionResult TestPost(TestPost tp)
{
return View(tp);
}
You probably need two actions in the Controller:
One that takes HTTP GET, and no parameters -- for the initial page load
One that takes HTTP POST, and the model as parameter -- for the postback
public ActionResult TestPost()
{
return View();
}
[HttpPost]
public ActionResult TestPost(TestPost post)
{
return View(post);
}
Also, since you're using Razor for the View, the syntax should be like this:
Your Name is #Model.name
change your view to
#model TestMVCProj.Models.TestPost
#{
ViewBag.Title ="TestPost";
}
#using (Html.BeginForm())
{
Html.TextBoxFor (x => x.name)
<input type="submit" />
}
Your Name is #Model.name

Categories