Navigation
Recherche
|
Build a server-side web app with .NET, C#, and HTMX
mercredi 18 décembre 2024, 10:00 , par InfoWorld
Create a.NET C# project To start, you’ll want the.NET CLI tool installed on your system, which is a fairly painless procedure. Once that’s done, you’ll have a dotnet command, which you can use to start a new application like so: $ dotnet new mvc -n QuoteApp This command creates a /QuoteApp directory. If we move into the new directory, we’ll see a simple project laid out for us. We can run it in dev mode like so: /QuoteApp $ dotnet run If you visit localhost:5265, you’ll see the starter screen like the one below: If you need to change the port or accept incoming requests from a domain other than localhost, you can modify the QuoteApp/Properties/launchSettings.json. As an example, in the http section, I modified the application to accept all incoming requests at port 3000: 'applicationUrl': ' The model class The layout of a typical.NET C# MVC application is similar to a Java Spring MVC application. Based on the Model View Controller design pattern, the first thing we want to do is add a model class. To start, create a new /Model directory (.NET conventionally capitalizes directory and file names) and then a QuoteItem.cs file: // Models/Quote.cs namespace QuoteApp.Models { public class Quote { public int Id { get; set; } public string Text { get; set; } public string Author { get; set; } } } This yields a simple data class to hold the Id, Text, and Author fields for our sample application. Java developers will notice the use of get; and set; shorthand to create the corresponding getter and setter for each field..NET’s namespace concept is similar to Java’s package, although packages in Java have lowercase names by convention. In our case, the directory structure and namespace agree, although this is not strictly required in C#. The repository class We’ll use a repository class for persisting the quotes users submit to our application. In a real application, the repository class would interact with a datastore. For our example, we’ll just use an in-memory list. Since our application is small, we can put the repository class directly into our root directory for now. Here’s the repository class: // QuoteRepository.cs using QuoteApp.Models; namespace QuoteApp { public class QuoteRepository { private static List _quotes = new List() { new Quote { Id = 1, Text = 'There is no try. Do or do not.', Author = 'Yoda' }, new Quote { Id = 2, Text = 'Strive not to be a success, but rather to be of value.', Author = 'Albert Einstein' } }; public List GetAll() { return _quotes; } public void Add(Quote quote) { // Simple ID generation (in real app, use database ID generation) quote.Id = _quotes.Any()? _quotes.Max(q => q.Id) + 1: 1; _quotes.Add(quote); } } } We’ll use a static block to declare and populate a _quotes List. Using that data, we provide two methods: GetAll() and Add(). GetAll() simply returns the List, while Add inserts the new Quote into it. We use a simple increment logic to create an ID for the new Quote. The controller class Now we can move on to the controller, which provides the application’s service layer: // Controllers/QuoteController.cs using Microsoft.AspNetCore.Mvc; using QuoteApp.Models; namespace QuoteApp.Controllers { public class QuoteController: Controller { private QuoteRepository _repository = new QuoteRepository(); public IActionResult Index() { var quotes = _repository.GetAll(); return View(quotes); } [HttpPost] public IActionResult Add(string text, string author) { if (!string.IsNullOrEmpty(text) &&!string.IsNullOrEmpty(author)) { var newQuote = new Quote { Text = text, Author = author }; _repository.Add(newQuote); //return Partial('_QuoteItem', newQuote); return PartialView('_QuoteItem', newQuote); } return BadRequest(); } } } The controller extends the abstract.NET MVC Controller class. It imports a couple of namespaces, one is from the.NET MVC library, and the other is our Quote model from the previous section. We then create a repository instance as a private member and define two public methods on it: Index() and Add(). Both methods return IActionResult. Index() takes the default GET HTTP method while Add() uses the [HttpPost] attribute to accept a POST. Attributes are similar to Java’s annotations and can decorate classes. In C#’s case, they also decorate namespaces. The Index() and Add() methods use functions from the MVC framework to form responses: View, PartialView, and BadRequest. Notice that Add() returns a partial view; this is because we are going to use HTMX to submit the new quote request with Ajax, and we’ll take the markup for just the new Quote and insert it on the front end. You’ll see this in the next section. The Index() method returns the view automatically associated with it, which is defined in the Views/Quote/Index.cshtml file. The view, which we’ll look at next, is provided with the list of quotes from the repository. The view class Our humble example only has two views, the index page and the quote. Here’s the index: // Views/Quote/Index.cshtml @model List Quotes @foreach (var quote in Model) { @await Html.PartialAsync('_QuoteItem', quote) } Add Quote The.cshtml file is a view defined in the Razor format, which is a templating technology that lets you use code and data in an HTML file. This is similar to other templating solutions like JSP, Thymeleaf, or Pug. It’s plain HTML with a dash of HTMX except for the server-side bits where we do the following: Import the list of quotes provided by the controller, using @model Use the list to iterate: @foreach (var quote in Model) Render each quote in the list Each quote is rendered with the line @await Html.PartialAsync('_QuoteItem', quote). PartialAsync means we are rendering a partial view (the quote template you’ll see shortly) using an asynchronous operation. Because it is async, we use the @await directive to wait for the operation to finish. The _QuoteItem template is defined like so: //Views/Quote/_QuoteItem.cshtml @model QuoteApp.Models.Quote @Model.Text - @Model.Author This template takes the Quote from the Add() controller method as its model and uses it to render a simple list item. The form Back in Index.cshtml, the form uses HTMX attributes to submit the fields in the background with Ajax. We’ll do the following: Send a POST Ajax request to.quote/add: hx-post='/quote/add' Put the response into the #quoteList element: hx-target='#quoteList' Put the response before the end of the target: hx-swap='beforeend' The net result is that the markup sent back in the response from the Add() service (the element) will be inserted directly at the end of the quote list. Launch the main program Program.cs is responsible for launching the program: // QuoteApp/Program.cs var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler('/Home/Error'); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllerRoute( name: 'default', pattern: '{controller=Home}/{action=Index}/{id?}'); app.MapControllerRoute( name: 'quote', pattern: 'quote/{action=Index}/{id?}', defaults: new { controller = 'Quote' }); app.Run(); This main file starts a new MVC application with the command-line arguments: WebApplication.CreateBuilder(args). The app generator adds a strict transport security layer if the developmentMode environment variable is not set. The site also redirects to https and serves static files by default. The UseRouting call means we’ll partake of the MVC routing plugin, and the UseAuthorization does the same for the MVC authorization plugin. Finally, we add the default Controller and our Quote controller. Notice the controller = “Quote” automatically maps to Controller/QuoteController. Conclusion Our new application is simple, but it gets the job done. It will list the quotes already submitted and allow us to add new ones dynamically when run with $ dotnet run, as shown here: Overall,.Net with C# is a well-thought-out platform for building apps in the MVC style, and HTMX gives us low-overhead Ajax. Check out the csharp-htmx application repository to see all the code for the demo.
https://www.infoworld.com/article/3625493/build-a-server-side-web-app-with-net-c-and-htmx.html
Voir aussi |
56 sources (32 en français)
Date Actuelle
mer. 18 déc. - 17:56 CET
|