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>
}