# ब्लॉग पोस्टों के लिए अस्तित्व फ्रेमवर्क जोड़ना

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

आप सभी स्रोत कोड पर ब्लॉग पोस्ट्स के लिए ढूंढ सकते हैं [जिटहब](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid/Blog)

**एक नेट कोर परियोजना में अस्तित्व फ्रेमवर्क जोड़ने पर श्रृंखला के भाग**

भाग 1 पाया जा सकता है [यहाँ](/blog/addingentityframeworkforblogpostspt1).

भाग 2 पाया जा सकता है [यहाँ](/blog/addingentityframeworkforblogpostspt2).

## परिचय

पिछले भागों में हम अपने ब्लॉग पोस्ट्स के लिए डाटाबेस और संदर्भ स्थापित किया है।

[TOC]

## नियंत्रक

Blogs के लिए आउट कंट्रोलर वास्तव में बहुत सरल हैं।

### ASP.NET MVC में वसा नियंत्रक पैटर्न

मैं MVC फ्रेमवर्क एक अच्छा अभ्यास है अपने नियंत्रक विधियों में यथासंभव कम से कम करने के लिए है।

'Fat Controller' antipattern है जहां नियंत्रक बहुत अधिक करता है।

1. बहुविध क्रियाओं में कोड का डुप्लीकेट
   एक कार्य कार्य का एक एकल इकाई होना चाहिए।
2. कोड जो परीक्षण करना कठिन है:
   'खाली कंट्रोलर युक्त होने के कारण \'\ आप कोड को परीक्षण करने में कठिनाई पैदा कर सकते हैं | . | परीक्षण को कोड के माध्यम से सभी संभव मार्गों का अनुसरण करने की कोशिश करनी चाहिए & #44; और यह कठिन हो सकता है यदि कोड अच्छा नहीं है & #39; - | संरचनात्मक और एक ही जिम्मेदारी पर केंद्रित
3. कोड जिसे बनाए रखना कठिन है:
   अनुप्रयोगों को बनाने के दौरान रख-रखाव एक प्रमुख चिंता है
4. कोड जो समझने में कठिन है
   विकासकर्ताओं के लिए यह एक प्रमुख चिंता है

### ब्लॉग नियंत्रक

ब्लॉग नियंत्रक अपेक्षाकृत सरल है।

```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` में विस्तृत है [पिछला पोस्ट](/blog/addingentityframeworkforblogpostspt2).

इन कार्यों में निम्नलिखित शामिल हैं।

- अनुक्रमणिका: यह ब्लॉग पोस्टों की सूची है `page` और `pageSize` पैरामीटर के रूप में
- दिखाएँ: यह व्यक्तिगत ब्लॉग पोस्ट है `slug` पद और `language` पैरामीटर के रूप में
- श्रेणी: यह एक दिए गए श्रेणी के लिए ब्लॉग पोस्टों की सूची है `category`, `page` और `pageSize` पैरामीटर के रूप में
- भाषा: यह एक दिए गए भाषा के लिए एक ब्लॉग पोस्ट दिखाता है `slug` और `language` पैरामीटर के रूप में
- Compat: यह पुराने ब्लॉग लिंक के लिए एक संगतता क्रिया है `slug` और `language` पैरामीटर के रूप में

### कैशिंग

जैसा कि एक में उल्लेख किया गया है [पूर्ववर्ती पोस्ट](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)})]
```

## दृश्य

ब्लॉग के लिए दृश्य अपेक्षाकृत सरल हैं। `Views/Blog` फोल्डर. मुख्य दृश्य हैं

### `_PostPartial.cshtml`

यह एकल ब्लॉग पोस्ट के लिए आंशिक दृश्य है `Post.cshtml` दृश्य

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

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

### `_BlogSummaryList.cshtml`

यह ब्लॉग पोस्टों की सूची के लिए आंशिक दृश्य है `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/addpagingwithhtmx) जो हमें ब्लॉग पोस्टों को पेज करने के लिए अनुमति देता है

### `_ListPost.cshtml`

 _सूची पोस्ट आंशिक दृश्य को सूची में व्यक्तिगत ब्लॉग पोस्टों को प्रदर्शित करने के लिए उपयोग किया जाता है `_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>
```

जैसा कि आप यहाँ देखेंगे, हमारे पास व्यक्तिगत ब्लॉग पोस्ट के लिए लिंक है।

हमारे पास भी है HTMX लिंक टैग के लिए वर्गों और भाषाओं को हम स्थानीयकृत पोस्ट और एक दिए गए वर्ग के लिए पोस्ट प्रदर्शित करने की अनुमति देता है

हम HTMX का उपयोग करने के दो तरीके यहाँ हैं-, एक जो पूरा यूआरएल देता है और एक जो सिर्फ HTML है।

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

यह दृष्टिकोण व्यक्तिगत ब्लॉग पोस्ट के लिए एक पूरा यूआरएल populates और उपयोग करता है `hx-boost` में HTMX का उपयोग करने के लिए अनुरोध 'boost' यह सेट करता है `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 टैग उपयोग करता है ब्लॉग पोस्टों के लिए वर्ग प्राप्त करने के लिए `hx-controller`, `hx-action`, `hx-push-url`, `hx-get`, `hx-target` और `hx-route-category` जब ब्लॉग पोस्टों के लिए वर्ग प्राप्त करने के लिए टैग `hx-push-url` को सेट किया गया है `true` ब्राउज़र इतिहास में यूआरएल को दबाने के लिए

यह हमारे अंदर भी उपयोग किया जाता है `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 अनुरोधों के लिए पूर्ण दृश्य या सिर्फ आंशिक दृश्य लौटाने की अनुमति देता है

## होम पेज

में `HomeController` हम इन ब्लॉग सेवाओं को भी संदर्भित है कि होम पेज के लिए नवीनतम ब्लॉग पोस्ट प्राप्त करें `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` होम पेज के लिए नवीनतम ब्लॉग पोस्ट प्राप्त करने के लिए `GetUserInfo` होम पेज के लिए उपयोगकर्ता जानकारी प्राप्त करने की विधि.

एक बार फिर यह एक HTMX अनुरोध है कि ब्लॉग पोस्टों के लिए आंशिक दृश्य लौटाएँ हम को होम पेज में ब्लॉग पोस्ट पृष्ठ करने की अनुमति देता है

## अंत में

हमारे अगले भाग में हम-'-हम कैसे हम का उपयोग करने के लिए खेदजनक विवरण में जाएँगे `IMarkdownBlogService` मार्क डाउन फ़ाइलों से ब्लॉग पोस्टों के साथ डाटाबेस को populate करने के लिए यह अनुप्रयोग का एक प्रमुख हिस्सा है क्योंकि यह हमें यह अनुमति देता है कि हम मार्क डाउंड फ़ाइलें के साथ डेटाबेस के साथ ब्लॉग पोस्ट्स populate के लिए उपयोग करें