Modell-Vy-Controller i ASP.NET Core

Modell-Vy-Controller (MVC) är ett designmönster som används i ASP.NET Core och i andra ramverk för att särskilja på ansvar och möjliggöra parallell utveckling. Detta mönster separerar användargränssnittet (View) från metoder som accepterar och svarar på förfrågningar (Controller) och från datastrukturer och klasser som hanterar data (Modeller).

MVC gör vyer, controller och modeller oberoende av varandra. Det här innebär att utvecklare samtidigt kan arbeta med olika delar av en applikation och att komponenter kan återanvändas i andra projekt.

En webbapplikation i ASP.NET Core består av en Programklass, en StartUp-klass, mellanprogram, modeller, vyer och controllers. Programklassen är ingångspunkten för programmet och StartUp-klassen hanterar applikationens konfiguration. Mellanprogram skapas för att hantera förfrågningar och generera svar avseende hela applikationen i stort.

Modell

En modell kan vara en datastruktur eller en klass som hanterar data i applikationen. Du kan skilja på datastrukturer och klasser som hanterar data i ditt program. Namnge datastrukturer som modeller (Model) och namnge klasser som hanterar data som arkiv (Repository). En modell är en datastruktur och en sådan modell kan ha metoder som gör det lättare att hämta och sätta värden för egenskaper.

public class AdDocument
{
    #region Variables

    public string id { get; set; }
    public string model_type { get; set; }
    public string web_domain_name { get; set; }
    public Int32 sort_value { get; set; }
    public IDictionary<string, string> ads;

    #endregion

    #region Constructors

    public AdDocument()
    {
        // Set values for instance variables
        this.id = Guid.NewGuid().ToString();
        this.model_type = "ad";
        this.web_domain_name = "";
        this.sort_value = 100;
        this.ads = new Dictionary<string, string>();

    } // End of the constructor

    #endregion

    #region Get methods

    public string Get(string key)
    {
        // Create the string to return
        string value = "";

        // Check if the dictionary contains the key
        if (this.ads.ContainsKey(key))
        {
            value = this.ads[key];
        }

        // Return the post
        return value;

    } // End of the Get method

    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);

    } // End of the ToString method

    #endregion

} // End of the class

Arkiv

Ett arkiv är en klass som hanterar data i en applikation. Ett arkiv kan vara generiskt och det har metoder som tar in och returnerar data. Ett arkiv kan användas i en controller eller i ett annat arkiv. Nedan är ett exempel på ett arkiv som hanterar annonser, det implementerar ett gränssnitt.

public class AdRepository : IAdRepository
{
    #region Variables

    private readonly ICosmosDatabaseRepository cosmos_database_repository;

    #endregion

    #region Constructors

    public AdRepository(ICosmosDatabaseRepository cosmos_database_repository)
    {
        // Set values for instance variables
        this.cosmos_database_repository = cosmos_database_repository;

    } // End of the constructor

    #endregion

    #region Add methods

    public async Task<bool> Add(AdDocument item)
    {
        // Create a document
        return await this.cosmos_database_repository.Add<AdDocument>(item);

    } // End of the Add method

    #endregion

    #region Update methods

    public async Task<bool> Upsert(AdDocument item)
    {
        // Upsert a document
        return await this.cosmos_database_repository.Upsert<AdDocument>(item);

    } // End of the Upsert method

    public async Task<bool> Update(AdDocument item)
    {
        // Replace a document
        return await this.cosmos_database_repository.Update<AdDocument>(item.id, item);

    } // End of the Update method

    #endregion

    #region Get methods

    public async Task<ModelItem<AdDocument>> GetById(string id)
    {
        // Return the post
        return await this.cosmos_database_repository.GetById<AdDocument>(id, id);

    } // End of the GetById method

    public async Task<ModelPage<AdDocument>> GetByWebDomainName(string web_domain_name, string sort_field, string sort_order, Int32 page_size, string ct)
    {
        // Make sure that sort variables are valid
        sort_field = GetValidSortField(sort_field);
        sort_order = GetValidSortOrder(sort_order);

        // Create the sql string
        string sql = $"SELECT VALUE a FROM a WHERE a.model_type = @model_type AND a.web_domain_name = @web_domain_name ORDER BY a.{sort_field} {sort_order}";

        // Create parameters
        SqlParameterCollection parameters = new SqlParameterCollection()
        {
            new SqlParameter("@model_type", "ad"),
            new SqlParameter("@web_domain_name", web_domain_name),
        };

        // Return the tuple
        return await this.cosmos_database_repository.GetListByQuery<AdDocument>(sql, parameters, page_size, ct);

    } // End of the GetByWebDomainName method

    public async Task<ModelPage<AdDocument>> GetBySearch(string keywords, string sort_field, string sort_order, Int32 page_size, string ct)
    {
        // Make sure that sort variables are valid
        sort_field = GetValidSortField(sort_field);
        sort_order = GetValidSortOrder(sort_order);

        // Check if there is keywords
        bool keywords_exists = string.IsNullOrEmpty(keywords) == false ? true : false;

        // Create the sql string
        string sql = "SELECT VALUE a FROM a WHERE a.model_type = @model_type ";
        if(keywords_exists == true)
        {
            sql += $"AND a.web_domain_name = @keywords ";
        }
        sql += $"ORDER BY a.{sort_field} {sort_order}";
                
        // Create parameters
        SqlParameterCollection parameters = new SqlParameterCollection();
        parameters.Add(new SqlParameter("@model_type", "ad"));
        if (keywords_exists == true)
        {
            parameters.Add(new SqlParameter("@keywords", keywords));
        }

        // Return the list
        return await this.cosmos_database_repository.GetListByQuery<AdDocument>(sql, parameters, page_size, ct);

    } // End of the GetBySearch method

    #endregion

    #region Delete methods

    public async Task<bool> DeleteOnId(string id)
    {
        // Delete a document
        return await this.cosmos_database_repository.DeleteOnId(id, id);

    } // End of the DeleteOnId method

    #endregion

    #region Validation

    public string GetValidSortField(string sort_field)
    {
        // Make sure that the sort field is valid
        if (sort_field != "sort_value" && sort_field != "web_domain_name")
        {
            sort_field = "web_domain_name";
        }

        // Return the string
        return sort_field;

    } // End of the GetValidSortField method

    public string GetValidSortOrder(string sort_order)
    {
        // Make sure that the sort order is valid
        if (sort_order != "ASC" && sort_order != "DESC")
        {
            sort_order = "ASC";
        }

        // Return the string
        return sort_order;

    } // End of the GetValidSortOrder method

    #endregion

} // End of the class

Controller

En controller är en mellanhand mellan modeller och vyer. En controller är ansvarig för att returnera vyer från HttpGet-förfrågningar och hantera HttpPost-förfrågningar från vyer. En controller har http-metoder, hanterar förfrågningar, bearbetar data genom att använda modeller och svarar genom att returnera vyer eller annan data. Du kan överföra data från en controller till en vy med hjälp av ViewBag, ViewData eller TempData. Mappnamnet för vyer överensstämmer normalt med namnet för den controller som de tillhör (home). Ett metodnamn i en controller överensstämmer ofta med namnet på en vy (index motsvarar index.cshtml).

public class homeController : Controller
{
    #region Variables

    private readonly IStaticPageRepository static_page_repository;
    private readonly IGroupRepository group_repository;
    private readonly IFinalRepository final_repository;

    #endregion

    #region Constructors

    public homeController(IStaticPageRepository static_page_repository, IGroupRepository group_repository, IFinalRepository final_repository)
    {
        // Set values for instance variables
        this.static_page_repository = static_page_repository;
        this.group_repository = group_repository;
        this.final_repository = final_repository;

    } // End of the constructor

    #endregion

    #region View methods

    [HttpGet]
    public IActionResult index()
    {
        // Get the start page
        StaticPage staticPage = this.static_page_repository.GetOneByConnectionId(1);
        staticPage = staticPage != null ? staticPage : new StaticPage();

        // Set form values
        ViewBag.BreadCrumbs = new List<BreadCrumb>(0);
        ViewBag.StaticPage = staticPage;

        // Return the view
        return View();

    } // End of the index method

    [HttpGet]
    public IActionResult search()
    {
        // Create the bread crumb list
        List<BreadCrumb> breadCrumbs = new List<BreadCrumb>(2);
        breadCrumbs.Add(new BreadCrumb("Startsidan", "/"));
        breadCrumbs.Add(new BreadCrumb("Sökresultat", "/home/search"));

        // Set form values
        ViewBag.BreadCrumbs = breadCrumbs;

        // Return the view
        return View("search");

    } // End of the search method

    [HttpGet]
    public IActionResult page(string id = "")
    {
        // Get the static page
        StaticPage staticPage = this.static_page_repository.GetOneByPageName(id);

        // Make sure that the static page not is null
        if (staticPage == null)
        {
            return NotFound();
        }

        // Create the bread crumb list
        List<BreadCrumb> breadCrumbs = new List<BreadCrumb>(2);
        breadCrumbs.Add(new BreadCrumb("Startsidan", "/"));
        breadCrumbs.Add(new BreadCrumb(staticPage.link_name, "/home/page/" + staticPage.page_name));

        // Set form values
        ViewBag.BreadCrumbs = breadCrumbs;
        ViewBag.StaticPage = staticPage;

        // Return the view
        return View();

    } // End of the page method

    [HttpGet]
    public IActionResult group(string id = "")
    {
        // Get the group
        Group post = this.group_repository.GetOneByPageName(id);
            
        // Make sure that the post not is null
        if (post == null)
        {
            return NotFound();
        }

        // Create the bread crumb list
        List<BreadCrumb> breadCrumbs = new List<BreadCrumb>(2);
        breadCrumbs.Add(new BreadCrumb("Startsidan", "/"));
        breadCrumbs.Add(new BreadCrumb(post.title, "/home/group/" + post.page_name));

        // Set form values
        ViewBag.BreadCrumbs = breadCrumbs;
        ViewBag.Group = post;

        // Return the view
        return View();

    } // End of the group method

    [HttpGet]
    public IActionResult error(string id = "")
    {
        // Set the connection id
        byte connectionId = 2;
        if (id == "404")
        {
            connectionId = 3;
        }
        else if(id == "401")
        {
            connectionId = 4;
        }
        else
        {
            connectionId = 2;
        }
               
        // Get the error page
        StaticPage staticPage = this.static_page_repository.GetOneByConnectionId(connectionId);
        staticPage = staticPage != null ? staticPage : new StaticPage();

        // Create the bread crumb list
        List<BreadCrumb> breadCrumbs = new List<BreadCrumb>(2);
        breadCrumbs.Add(new BreadCrumb("Startsidan", "/"));
        breadCrumbs.Add(new BreadCrumb(staticPage.link_name, "/home/error/" + id.ToString()));

        // Set form values
        ViewBag.BreadCrumbs = breadCrumbs;
        ViewBag.StaticPage = staticPage;

        // Return the view
        return View();

    } // End of the error method

    #endregion

    #region Post methods

    [HttpPost]
    public IActionResult search(IFormCollection collection)
    {
        // Get the keywords
        string keywordString = collection["txtSearch"];

        // Return the url with search parameters
        return Redirect("/home/search?kw=" + WebUtility.UrlEncode(keywordString));

    } // End of the search method

    #endregion

    #region Ajax methods

    [HttpGet]
    public IActionResult get_group_standings(Int32 id = 0)
    {
        // Get all the groups
        IList<Group> groups = this.group_repository.GetActiveByStaticPageId(id, "sort_value", "ASC");

        // Add data to the form
        ViewBag.Groups = groups;

        // Return the partial view
        return PartialView("_group_standings");

    } // End of the get_group_standings method

    [HttpGet]
    public IActionResult get_final_games(Int32 id = 0)
    {
        // Get final games
        IList<Final> finals = this.final_repository.GetActiveByStaticPageId(id, "sort_value", "ASC");

        // Add data to the form
        ViewBag.Finals = finals;

        // Return the partial view
        return PartialView("_final_games");

    } // End of the get_final_games method

    [HttpGet]
    public IActionResult get_group_details(Int32 id = 0)
    {
        // Get the group
        Group group = this.group_repository.GetOneById(id);

        // Get teams and games
        ViewBag.Teams = this.group_repository.GetTeamsFromXml(group.data_content);
        ViewBag.Games = this.group_repository.GetGamesFromXml(group.data_content);
        ViewBag.Matches = this.group_repository.GetUpcomingMatchesFromXml(group.data_content);

        // Return the partial view
        return PartialView("_group_details");

    } // End of the get_group_details method

    [HttpGet]
    public async Task<string> get_news_as_html(string kw = "")
    {
        // Create the string to return
        string html = "";

        // Create the culture
        CultureInfo cultureInfo = new CultureInfo("sv-SE");

        // Get news items
        IList<NewsItem> newsItems = await this.static_page_repository.GetNewsFromRSS(kw);

        // Loop the array
        for (int i = 0; i < newsItems.Count; i++)
        {
            // Get the date
            DateTime date = DateTime.UtcNow;

            try
            {
                date = DateTime.ParseExact(newsItems[i].pub_date, "ddd, d MMM yyyy HH:mm:ss GMT", CultureInfo.InvariantCulture);
            }
            catch (Exception ex)
            {
                string exMessage = ex.Message;
            }

            // Create the html
            html += "<div class=\"annytab-news-item-container\">";
            html += "<a href=\"" + newsItems[i].link + "\" target=\"_blank\" class=\"annytab-news-item-title\">" + newsItems[i].title + "</a><br />";
            html += "<div class=\"annytab-news-item-date\">" + date.ToString("d MMMM yyyy HH:mm:ss", cultureInfo) + "</div>";
            html += "<div class=\"annytab-basic-bread-text\">" + newsItems[i].description + "</div>";
            html += "</div>";
        }

        // Powered by Google News
        html += "<div style=\"padding: 5px;margin:0px 0px 20px 0px;font-size:14px;\">Nyheterna kommer från <a href=\"https://news.google.com/news/search/section/q/" + kw + "/" + kw + "?hl=sv&gl=SE&ned=sv_se\">Google News</a></div>";

        // Return the string
        return html;

    } // End of the get_news_as_html method

    #endregion

} // End of the class

Vy

En vy ansvarar för att presentera information till slutanvändare och för att hantera inmatning från slutanvändare. Du kan använda HTML, Razor och JavaScript i vyer. En vy beror vanligtvis på en layoutvy och den kan innehålla partiella vyer. En vy kan få data från en controller via ViewBag, ViewData eller TempData. En controller bestämmer vilka metoder som används för att överföra data till en vy.

@using Annytab.Models
@{
    // Get form values
    StaticPage staticPage = ViewBag.StaticPage;

    // Set the web address
    string web_address = "http://www.fotbollstabeller.nu";

    // Set meta data
    ViewBag.Title = staticPage.title;
    ViewBag.MetaDescription = staticPage.meta_description;
    ViewBag.MetaKeywords = staticPage.meta_keywords;
    ViewBag.MetaCanonical = web_address;
    ViewBag.MetaRobots = staticPage.meta_robots;

    // Set the layout for the page
    Layout = "/Views/shared_front/_standard_layout.cshtml";
}

@*Title*@
<h1>@ViewBag.Title</h1>

@*Share content*@
<div class="annytab-share-container">
    <div class="annytab-share-button"><div class="fb-like" data-layout="button" data-action="like" data-show-faces="false" data-share="true" data-href="@web_address"></div></div>
    <div class="annytab-share-button"><a href="https://twitter.com/share" data-count="none" class="twitter-share-button" data-href="@web_address" data-lang="sv">Tweet</a></div>
</div>

@*Google ad*@
<div class="annytab-ad-slot-container-top">
    <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
    <!-- fotbollstabeller.nu - responsive -->
    <ins class="adsbygoogle"
         style="display:block"
         data-ad-client="ca-pub-3070633924070834"
         data-ad-slot="4984893802"
         data-ad-format="auto"></ins>
    <script>
        (adsbygoogle = window.adsbygoogle || []).push({});
    </script>
</div>

@*Groups*@
<div id="groupsContainer" data-id="@staticPage.id" class="annytab-list-container">
    <div class="annytab-basic-loading-container"><i class="fas fa-spinner fa-pulse fa-4x fa-fw"></i><div style="margin-top:10px;">Laddar tabeller...</div></div>
</div>

@*Description*@
<h2 class="annytab-basic-title-container">Beskrivning</h2>
<div class="annytab-basic-bread-text" style="padding:5px;">@Html.Raw(staticPage.main_content) </div>

@*Google ad*@
<div class="annytab-ad-slot-container-bottom">
    <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
    <!-- fotbollstabeller.nu - responsive -->
    <ins class="adsbygoogle"
         style="display:block"
         data-ad-client="ca-pub-3070633924070834"
         data-ad-slot="4984893802"
         data-ad-format="auto"></ins>
    <script>
        (adsbygoogle = window.adsbygoogle || []).push({});
    </script>
</div>

@*News*@
<div id="newsContainer" data-search="@staticPage.news_search_string" style="display:none;">
    <h2 class="annytab-basic-title-container">Nyheter</h2>
</div>

@section scripts {
    <script type="text/javascript">

        // Get containers
        var newsContainer = $('#newsContainer');
        var groupsContainer = $('#groupsContainer');

        // Get group standings
        $.ajax({
            type: 'GET',
            url: '/home/get_group_standings/' + groupsContainer.data('id'),
            dataType: 'html',
            success: function (data) {
                groupsContainer.html(data);
            },
            error: function (xhr) {
                groupsContainer.html('');
            } 
        });

        // Get news from google
        if (newsContainer.data("search") != "")
        {
            $.ajax({
                type: 'GET',
                url: '/home/get_news_as_html?kw=' + encodeURIComponent(newsContainer.data("search")),
                dataType: 'html',
                success: function (data) {
                    newsContainer.append(data);
                    newsContainer.slideDown(2000);
                },
                error: function (xhr) {
                    newsContainer.html('');
                }
            });
        }
    </script>
}

Lämna ett svar

E-postadressen publiceras inte. Obligatoriska fält är märkta *