This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Potete trovare tutto il codice sorgente per i post del blog su GitHubCity name (optional, probably does not need a translation)
Parti 1 e 2 della serie relativa all'aggiunta di Entity Framework a un progetto.NET Core.
Si può trovare la parte 1 qui.
Si può trovare la parte 2 qui.
Nelle parti precedenti abbiamo creato il database e il contesto per i nostri post sul blog, e aggiunto i servizi per interagire con il database. In questo post, spiegheremo come questi servizi funzionano ora con i controllori e le opinioni esistenti.
I controller per i Blog sono davvero molto semplici; in linea con l'evitare l'antipattern 'Fat Controller' (un pattern che abbiamo ideato all'inizio dei giorni ASP.NET MVC).
I MVC inquadra una buona pratica è quello di fare il meno possibile nei vostri metodi di controllo. Questo perché il responsabile del trattamento è responsabile per la gestione della richiesta e la restituzione di una risposta. Non dovrebbe essere responsabile della logica aziendale della domanda. Questa è la responsabilità del modello.
L'antipattern 'Fat Controller' è dove il controller fa troppo. Ciò può portare a una serie di problemi, tra cui:
Il blog controller è relativamente semplice. Ha 4 azioni principali (e una 'azione compatibile' per i vecchi collegamenti del blog). Questi sono:
Task<IActionResult> Index(int page = 1, int pageSize = 5)
Task<IActionResult> Show(string slug, string language = BaseService.EnglishLanguage)
Task<IActionResult> Category(string category, int page = 1, int pageSize = 5)
Task<IActionResult> Language(string slug, string language)
IActionResult Compat(string slug, string language)
A loro volta queste azioni chiamano il IBlogService
per ottenere i dati di cui hanno bisogno. La IBlogService
è dettagliata nel Post precedente.
A loro volta, queste azioni sono le seguenti:
page
e pageSize
come parametri. Questo è per la paginazione. dei risultati.slug
del posto e del language
come parametri. THis è il metodo che state usando attualmente per leggere questo post sul blog.category
, page
e pageSize
come parametri.slug
e language
come parametri.slug
e language
come parametri.Come indicato in un posto precedente implementiamo OutputCache
e ResponseCahce
per nascondere i risultati dei post del blog. Questo migliora l'esperienza utente e riduce il carico sul server.
Queste sono implementate utilizzando i decoratori di azione appropriati che specificano i parametri utilizzati per l'azione (così come hx-request
per le richieste HTMX). Per l'esame con Index
Noi li precisiamo:
[ResponseCache(Duration = 300, VaryByHeader = "hx-request", VaryByQueryKeys = new[] {nameof(page), nameof(pageSize)}, Location = ResponseCacheLocation.Any)]
[OutputCache(Duration = 3600, VaryByHeaderNames = new[] {"hx-request"} ,VaryByQueryKeys = new[] { nameof(page), nameof(pageSize)})]
Le viste per il blog sono relativamente semplici. Sono per lo più solo una lista di post sul blog, con alcuni dettagli per ogni post. I punti di vista sono nella Views/Blog
Cartella. I punti di vista principali sono:
_PostPartial.cshtml
Questa è la vista parziale per un singolo post sul blog. E 'utilizzato all'interno della nostra Post.cshtml
vista.
@model Mostlylucid.Models.Blog.BlogPostViewModel
@{
Layout = "_Layout";
}
<partial name="_PostPartial" model="Model"/>
_BlogSummaryList.cshtml
Questa è la vista parziale per una lista di post sul blog. E 'utilizzato all'interno della nostra Index.cshtml
vista così come nella homepage.
@model Mostlylucid.Models.Blog.PostListViewModel
<div class="pt-2" id="content">
@if (Model.TotalItems > Model.PageSize)
{
<pager
x-ref="pager"
link-url="@Model.LinkUrl"
hx-boost="true"
hx-push-url="true"
hx-target="#content"
hx-swap="show:none"
page="@Model.Page"
page-size="@Model.PageSize"
total-items="@Model.TotalItems"
class="w-full"></pager>
}
@if(ViewBag.Categories != null)
{
<div class="pb-3">
<h4 class="font-body text-lg text-primary dark:text-white">Categories</h4>
<div class="flex flex-wrap gap-2 pt-2">
@foreach (var category in ViewBag.Categories)
{
<a hx-controller="Blog" hx-action="Category" hx-push-url="true" hx-get hx-target="#contentcontainer" hx-route-category="@category" href>
<span class="inline-block rounded-full dark bg-blue-dark px-2 py-1 font-body text-sm text-white outline-1 outline outline-green-dark dark:outline-white">@category</span>
</a>
}
</div>
</div>
}
@foreach (var post in Model.Posts)
{
<partial name="_ListPost" model="post"/>
}
</div>
In questo modo si utilizza il _ListPost
vista parziale per visualizzare i singoli post del blog insieme con il aiutante tag paging che ci permette di leggere i post del blog.
_ListPost.cshtml
La _La vista parziale di Listpost è usata per visualizzare i singoli post del blog nell'elenco. Viene utilizzato all'interno del _BlogSummaryList
vista.
@model Mostlylucid.Models.Blog.PostListModel
<div class="border-b border-grey-lighter pb-8 mb-8">
<a asp-controller="Blog" asp-action="Show" hx-boost="true" hx-swap="show:window:top" hx-target="#contentcontainer" asp-route-slug="@Model.Slug"
class="block font-body text-lg font-semibold transition-colors hover:text-green text-blue-dark dark:text-white dark:hover:text-secondary">@Model.Title</a>
<div class="flex space-x-2 items-center py-4">
@foreach (var category in Model.Categories)
{
<a hx-controller="Blog" hx-action="Category" class="rounded-full bg-blue-dark font-body text-sm text-white px-2 py-1 outline outline-1 outline-white" hx-push-url="true" hx-get hx-target="#contentcontainer" hx-route-category="@category" href>@category
</a>
}
@{ var languageModel = (Model.Slug, Model.Languages, Model.Language); }
<partial name="_LanguageList" model="languageModel"/>
</div>
<div class="block font-body text-black dark:text-white">@Model.Summary</div>
<div class="flex items-center pt-4">
<p class="pr-2 font-body font-light text-primary light:text-black dark:text-white">
@Model.PublishedDate.ToString("f")
</p>
<span class="font-body text-grey dark:text-white">//</span>
<p class="pl-2 font-body font-light text-primary light:text-black dark:text-white">
@Model.ReadingTime
</p>
</div>
</div>
Come si se qui abbiamo un link al singolo post del blog, le categorie per il post, le lingue in cui il post è disponibile, il riassunto del post, la data pubblicata e l'ora di lettura.
Abbiamo anche i tag link HTMX per le categorie e le lingue per permetterci di visualizzare i post localizzati e i post per una determinata categoria.
Abbiamo due modi di utilizzare HTMX qui, uno che fornisce l'URL completo e uno che è 'HTML solo' (cioè. URL). Questo perché vogliamo utilizzare l'URL completo per le categorie e le lingue, ma non abbiamo bisogno dell'URL completo per il post del singolo blog.
<a asp-controller="Blog" asp-action="Show" hx-boost="true" hx-swap="show:window:top" hx-target="#contentcontainer" asp-route-slug="@Model.Slug"
Questo approccio popola un URL completo per il singolo post del blog e utilizza hx-boost
per "rafforzare" la richiesta di utilizzare HTMX (questo imposta la hx-request
intestazione a true
).
<a hx-controller="Blog" hx-action="Category" class="rounded-full bg-blue-dark font-body text-sm text-white px-2 py-1 outline outline-1 outline-white" hx-push-url="true" hx-get hx-target="#contentcontainer" hx-route-category="@category" href>@category
</a>
In alternativa questo approccio utilizza i tag HTMX per ottenere le categorie per i post del blog. In questo modo si utilizza il hx-controller
, hx-action
, hx-push-url
, hx-get
, hx-target
e hx-route-category
tags per ottenere le categorie per i post del blog mentre hx-push-url
è impostato a true
per spingere l'URL alla cronologia del browser.
E 'utilizzato anche all'interno della nostra Index
Metodo di azione per le richieste HTMX.
public async Task<IActionResult> Index(int page = 1, int pageSize = 5)
{
var posts =await blogService.GetPagedPosts(page, pageSize);
if(Request.IsHtmx())
{
return PartialView("_BlogSummaryList", posts);
}
posts.LinkUrl = Url.Action("Index", "Blog");
return View("Index", posts);
}
Dove ci permette di restituire la visione completa o solo la visione parziale per le richieste HTMX, dando una 'SPA' come esperienza.
Nella HomeController
ci riferiamo anche a questi servizi di blog per ottenere gli ultimi post del blog per la home page. Questo è fatto nel Index
metodo d'azione.
public async Task<IActionResult> Index(int page = 1,int pageSize = 5)
{
var authenticateResult = GetUserInfo();
var posts =await blogService.GetPagedPosts(page, pageSize);
posts.LinkUrl= Url.Action("Index", "Home");
if (Request.IsHtmx())
{
return PartialView("_BlogSummaryList", posts);
}
var indexPageViewModel = new IndexPageViewModel
{
Posts = posts, Authenticated = authenticateResult.LoggedIn, Name = authenticateResult.Name,
AvatarUrl = authenticateResult.AvatarUrl
};
return View(indexPageViewModel);
}
Come vedrete qui, usiamo il IBlogService
per ottenere gli ultimi post del blog per la home page. Noi usiamo anche il GetUserInfo
metodo per ottenere le informazioni dell'utente per la home page.
Ancora una volta questo ha una richiesta HTMX di restituire la vista parziale per i post del blog per permetterci di pagina i post del blog nella home page.
Nella nostra prossima parte andremo nel dettaglio straziante di come usiamo il IMarkdownBlogService
per popolare il database con i post del blog dai file markdown. Questa è una parte chiave dell'applicazione in quanto ci permette di utilizzare i file markdown per popolare il database con i post del blog.