# Προσθήκη Πλαίσιο Οντότητας για Δημοσιεύσεις στο Blog (Παρουσίαση ΜSK1

<!--category-- ASP.NET, Entity Framework -->
<datetime class="hidden">2024-08-16T18:00</datetime>

Μπορείτε να βρείτε ολόκληρο τον κώδικα πηγής για τα άρθρα στο blog [GitHub](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid/Blog)

**Μερικά τμήματα 1 ΜSK1 2 της σειράς σχετικά με την προσθήκη του Entity Framework σε ένα έργο κεντρικής εμβέλειας .NET**

Μέρος 1 επιχειρήσεις μπορούν να βρεθούν [ΕΔΩ](/blog/addingentityframeworkforblogpostspt1).

Μέρος 2 επιχειρήσεις μπορούν να βρεθούν [ΕΔΩ](/blog/addingentityframeworkforblogpostspt2).

## Εισαγωγή

Στα προηγούμενα μέρη, δημιουργήσαμε τη βάση δεδομένων και το πλαίσιο για τα ιστολόγια μας, και πρόσθεσε τις υπηρεσίες να αλληλεπιδράσουν με την βάση δεδομένα. Σε αυτό το postM SK2 θα αναλυθούμε πώς αυτές οι υπηρεσίες τώρα λειτουργούν με τους υπάρχοντες ελεγκτές και τις απόψειςΜSK3

[TOC]

## Ελέγχοντες

Οι ελεγκτές για τα Blogs είναι πραγματικά αρκετά απλοί; σε συνάρτηση με την αποφυγή του 'Fat ControllerM SK2 αντιπροσωπεία ΜSK3 πρότυπο ιδεοποιήσαμε νωρίς στην ASPMSKA4NET MVC ημέρεςMKA5

### Το πρότυπο ελέγχου λίπους στο ASP.NET MVC

I MVC frameworks μια καλή πρακτική είναι να κάνετε όσο το δυνατόν λιγότερο στις μεθόδους ελέγχου σας. Αυτό συμβαίνει επειδή ο ελεγκτής είναι υπεύθυνος για την επεξεργασία του αιτήματος και την επιστροφή μιας απάντησηςΜSK1 Δεν πρέπει να ευθύνεται για τη επιχειρηματική λογική της εφαρμογής.Αυτή είναι η ευθύνη του μοντέλου

Το 'Fat Controller' αντιπροσωπεία είναι όπου ο ελεγκτής κάνει πάρα πολύM SK2 Αυτό μπορεί να οδηγήσει σε ένα αριθμό προβλημάτωνMSKA3 συμπεριλαμβανομένωνMKA4

1. Διπλασιασμός κώδικα σε πολλαπλές δράσεις:
   Μια δράση θα πρέπει να είναι μια ενιαία μονάδα εργασίας, απλά λαμβάνοντας το μοντέλο και επιστρέφοντας την προβολήΜSK1 Εάν βρείτε τον εαυτό σας επαναλαμβανόμενος κώδικα σε πολλαπλές ενέργειες, αυτό είναι ένα σημάδι ότι θα έπρεπε να αναπαράγετε αυτόν τον κωδικό σε μια ξεχωριστή μέθοδοM SK3
2. Κώδικα που είναι δύσκολο να δοκιμάσετε:
   Έχοντας ' αναπληρώσεις ελεγκτές ΜSK1 μπορεί να σας κάνει δύσκολο να δοκιμάσετε τον κωδικό Η . αναπληρώνει το Testing θα πρέπει να προσπαθήσει να ακολουθήσει όλα τα πιθανά μονοπάτια μέσω του κώδικα ΜSK3 και αυτό μπορεί να είναι δύσκολο αν ο κωδικός δεν είναι καλά - αναπληρωμένο και επικεντρωθεί σε μια ενιαία ευθύνη
3. Κώδικα που είναι δύσκολο να διατηρηθεί: επιχειρήσεις
   Η διατήρηση είναι μια βασική ανησυχία κατά την κατασκευή εφαρμογών. Έχοντας 'kitchen sinkM SK2 μέθοδοι δράσης μπορεί εύκολα να οδηγήσει σε εσάς και άλλους προγραμματιστές χρησιμοποιώντας τον κώδικα για να κάνετε αλλαγές που σπάζουν άλλα τμήματα της εφαρμογήςΜSK3
4. Κώδικα που είναι δύσκολο να κατανοήσουμε:
   Αυτό είναι μια βασική ανησυχία για τους προγραμματιστές. Εάν εργάζεστε σε ένα έργο με μεγάλη βάση κωδικώνΜSK1 μπορεί να είναι δύσκολο να καταλάβετε τι συμβαίνει σε μια δράση ελέγχου εάν κάνει πάρα πολύ.

### Ο έλεγχος του blog

Ο διαχειριστής του ιστολογίου είναι σχετικά απλός. Έχει ΜSK1 κύριες ενέργειες ΜSK2 και μία ' συμβατή δράση ΜΚ4 για τους παλιούς συνδέσμους blog ΜΣΚ5 Αυτά είναι ΜСК6

```csharp
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)
```

Ως εκ τούτου, οι ενέργειες αυτές αποκαλούν `IBlogService` για να αποκτήσουν τα δεδομένα που χρειάζονται. `IBlogService` Περιγράφεται λεπτομερώς στο [Προηγούμενο post](/blog/addingentityframeworkforblogpostspt2).

Από την άλλη πλευρά, οι ενέργειες αυτές είναι ως εξής:

- Δείκτης:Αυτό είναι ο κατάλογος των αναρτήσεων στο blog ΜSK1επιβεβαιώσεις στην Αγγλική γλώσσα;θα μπορούμε να επεκτείνουμε αυτό αργότερα για να επιτρέψουμε πολλές γλώσσεςM SK3Θα δείτε ότι χρειάζεται `page` και `pageSize` ως παραμέτρους.Αυτό είναι για τη σελίδαΜSK1 των αποτελεσμάτων.
- Εμφάνιση:Αυτή είναι η ατομική ανάρτηση στο blogΜSK1Πρέπει να `slug` Από την εφημερίδα και το `language` ως παραμέτρους.Αυτή είναι η μέθοδος που χρησιμοποιείτε για να διαβάσετε αυτό το blog post.
- Κατηγορία:Αυτό είναι ο κατάλογος των blog posts για μια συγκεκριμένη κατηγορίαΜSK1Πρέπει να `category`, `page` και `pageSize` Οι παράμετροι .
- Γλώσσα: Αυτό δείχνει ένα blog post για μια δεδομένη γλώσσαΜSK1 Χρειάζεται το `slug` και `language` Οι παράμετροι .
- Compat: Αυτό είναι μια δράση συμβατότητας για τους παλιούς συνδέσμους blog. Χρειάζεται το `slug` και `language` Οι παράμετροι .

### Κατσάκι

Όπως αναφέρθηκε σε ένα [Προηγούμενο post](https://www.mostlylucid.net/blog/aspnetcachingwithhtmx) εφαρμόζουμε `OutputCache` και `ResponseCahce` για την κρυπτογράφηση των αποτελεσμάτων των ιστολογικών δημοσιεύσεων.Αυτό βελτιώνει την εμπειρία του χρήστη και μειώνει το φορτίο στον διακομιστή.

Αυτά εφαρμόζονται με τη χρήση των κατάλληλων διακοσμητών δράσης που προσδιορίζουν τις παραμέτρους που χρησιμοποιούνται για την δράση ( αναφορές, καθώς και `hx-request` για τις αιτήσεις HTMX). Για παράδειγμα με `Index` Εμείς αναφέρουμε αυτές τις: επιχειρήσεις

```csharp
    [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)})]
```

## Προβλέψεις

Οι απόψεις για το blog είναι σχετικά απλές. Είναι κατά κύριο λόγο μόνο μια λίστα με τις δημοσιεύσεις στο blogΜSK1 με λίγες λεπτομέρειες για κάθε post. `Views/Blog` φάκελο. Οι κύριες προβολές είναιΜSK1

### `_PostPartial.cshtml`

Αυτή είναι η μερική εικόνα για ένα ενιαίο blog post. Χρησιμοποιείται μέσα στο δικό μας `Post.cshtml` ΔΙΑΒΑΣΤΕ ΕΠΙΧΕΙΡΕΥΣΗ

```razor
@model Mostlylucid.Models.Blog.BlogPostViewModel

@{
    Layout = "_Layout";
}
<partial name="_PostPartial" model="Model"/>
```

### `_BlogSummaryList.cshtml`

Αυτή είναι η μερική προβολή για μια λίστα blog posts. Χρησιμοποιείται μέσα στο δικό μας `Index.cshtml` Δείτε επίσης και στην ιστοσελίδα.

```razor
@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>
```

Αυτό χρησιμοποιεί το `_ListPost` μερική προβολή για την εμφάνιση των ατομικών δημοσιεύσεων στο blog μαζί με το [Ετικέτες Βοηθός](/blog/addpagingwithhtmx) που μας επιτρέπει να τοποθετήσουμε τα άρθρα του blog.

### `_ListPost.cshtml`

Η _Η μερική προβολή της λίστας χρησιμοποιείται για την εμφάνιση των ατομικών δημοσιεύσεων στο blog στη λίστα. Χρησιμοποιείται εντός του `_BlogSummaryList` ΔΙΑΒΑΣΤΕ ΕΠΙΧΕΙΡΕΥΣΗ

```razor
@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>
```

Όπως σας ενδιαφέρει' αναμένεται να δείτε εδώ έχουμε μια σύνδεση με την ατομική ανάρτηση blog, αναμένετε τις κατηγορίες για το postΜSK2 αναμένω τις γλώσσες που είναι διαθέσιμες στο post, αναμένει τη συνοπτική της ανάρτησηςM SK4 αναμέρει την ημερομηνία δημοσίευσης και τον χρόνο ανάγνωσηςMK5 αναμένοντας

Έχουμε επίσης ετικέτες σύνδεσης HTMX για τις κατηγορίες και τις γλώσσες που μας επιτρέπουν να εμφανίσουμε τα εντοπισμένα μηνύματα και τις δημοσιεύσεις για μια συγκεκριμένη κατηγορία.

Έχουμε δύο τρόπους για να χρησιμοποιήσουμε το HTMX εδώ, ένα που δίνει την πλήρη URL και ένα που είναι 'HTML μόνοM SK2 (ΜSK4MSKA5Δεν υπάρχει URLMSKI6Αυτό συμβαίνει επειδή θέλουμε να χρησιμοποιούμε το πλήρες URL για τις κατηγορίες και τις γλώσσεςMSKE7 αλλά δεν έχουμε ανάγκη η πλήρης URL για τη μεμονωμένη ανάρτηση στο blogMISK9

```razor
 <a asp-controller="Blog" asp-action="Show" hx-boost="true"  hx-swap="show:window:top"  hx-target="#contentcontainer" asp-route-slug="@Model.Slug"
```

Αυτή η προσέγγιση εντοπίζει μια πλήρη URL για την ατομική ανάρτηση στο blog και χρησιμοποιεί `hx-boost` 'boost ΜSK1 το αίτημα για χρήση HTMX ΜSK2this καθορίζει την `hx-request` Ο επικεφαλής για `true`).

```razor
  <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>
```

Εναλλακτικά, αυτή η προσέγγιση χρησιμοποιεί τις ετικέτες HTMX για να πάρει τις κατηγορίες για τα άρθρα του blog. Αυτό χρησιμοποιεί την `hx-controller`, `hx-action`, `hx-push-url`, `hx-get`, `hx-target` και `hx-route-category` Tags για να πάρετε τις κατηγορίες για τα άρθρα του blog ενώ `hx-push-url` Έχει καθοριστεί `true` για να πιέσετε το URL στο ιστορικό του προγράμματος περιήγησης.

Χρησιμοποιείται και στο εσωτερικό μας `Index` Μέθοδος δράσης για τις αιτήσεις HTMX.

```csharp
  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);
    }
```

Όπου μας επιτρέπει είτε να επιστρέψουμε την πλήρη προβολή ή μόνο τη μερική προβολία για τις αιτήσεις HTMX, δίνει μια ΜSK1SPA' όπως η εμπειρίαM SK3

## Home Σελίδα

Στον `HomeController` αναφερόμαστε επίσης σε αυτές τις υπηρεσίες blog για να λάβουμε τα πιο πρόσφατα άρθρα blog για την αρχική σελίδα. Αυτό γίνεται στο `Index` Μέθοδος δράσης.

```csharp
   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);
    }
```

Όπως θα σας αρέσει' αναμένεται να δείτε εδώ χρησιμοποιούμε το `IBlogService` για να πάρετε τις τελευταίες δημοσιεύσεις στο blog για την αρχική σελίδα. Χρησιμοποιούμε επίσης το `GetUserInfo` μέθοδος για τη λήψη των πληροφοριών του χρήστη για την αρχική σελίδα.

Και πάλι αυτό έχει ένα αίτημα HTMX για να επιστρέψει την εν μέρει προβολή των δημοσιεύσεων στο blog, ώστε να μας επιτρέπει να τοποθετήσουμε τις δημοσιεύσεις του blog στην αρχική σελίδα.

## Στο συμπέρασμα

Στο επόμενο τμήμα μας θα ανακαλύψουμε' θα πάμε σε λεπτομέρειες για το πώς χρησιμοποιούμε την `IMarkdownBlogService` για να λαμβάνουμε τη βάση δεδομένων με τις δημοσιεύσεις του blog από τα αρχεία μάρκας.Αυτό είναι ένα βασικό μέρος της εφαρμογής, καθώς μας επιτρέπει να χρησιμοποιούμε τα αρχείο μάρκετινγκ για να Λαμβάνεται η βάση δεδομένα με τις αναρτήσεις του blog.