I am being tasked with creating an ASP.NET Core 6 MVC web app that does the following:
Build an app that allows a user to search through the given API. After searching, display the results and allow a user to click to the corresponding iTunes page. You can search iTunes by using the iTunes Search AP here: https://itunes.apple.com/search?term=
Include a server side component that tracks how many clicks per result are made within the app and a create a view that displays the count of clicks
When the user clicks on a search result, the app should redirect to the album/video/app in the itunes store.
I am new to .NET and C# and would like some guidance on what steps I should take. I have created the web page with basic HTML and am now stuck on the backend side. I am going to be using the MVC design pattern so I understand that I will need a model and a controller but am not sure what to do. Can anyone help me at all on how I can go about solving this? I will share all the code I have so far along with my frontend.
Model folder - ItunesSearchResults.cs:
namespace ReachMobieItunesMVC.Models;
/// <summary>
/// Retrieves data from API.
/// </summary>
///
public class ItunesSearchResults
{
public int resultCount { get; set; }
public List<Result> results { get; set; }
}
public class GroupedResult
{
public int TotalCount { get; set; }
public string Type { get; set; }
public List<Result> results { get; set; }
}
public class Result
{
public string wrapperType { get; set; }
public string kind { get; set; }
public int collectionId { get; set; }
public int trackId { get; set; }
public string artistName { get; set; }
public string collectionName { get; set; }
public string trackName { get; set; }
public string collectionCensoredName { get; set; }
public string trackCensoredName { get; set; }
public int collectionArtistId { get; set; }
public string collectionArtistViewUrl { get; set; }
public string collectionViewUrl { get; set; }
public string trackViewUrl { get; set; }
public string previewUrl { get; set; }
public string artworkUrl30 { get; set; }
public string artworkUrl60 { get; set; }
public string artworkUrl100 { get; set; }
public double collectionPrice { get; set; }
public double trackPrice { get; set; }
public double trackRentalPrice { get; set; }
public double collectionHdPrice { get; set; }
public double trackHdPrice { get; set; }
public double trackHdRentalPrice { get; set; }
public DateTime releaseDate { get; set; }
public string collectionExplicitness { get; set; }
public string trackExplicitness { get; set; }
public int discCount { get; set; }
public int discNumber { get; set; }
public int trackCount { get; set; }
public int trackNumber { get; set; }
public int trackTimeMillis { get; set; }
public string country { get; set; }
public string currency { get; set; }
public string primaryGenreName { get; set; }
public string contentAdvisoryRating { get; set; }
public string shortDescription { get; set; }
public string longDescription { get; set; }
public bool hasITunesExtras { get; set; }
public int? artistId { get; set; }
public string artistViewUrl { get; set; }
public bool? isStreamable { get; set; }
public string description { get; set; }
public string copyright { get; set; }
public int? amgArtistId { get; set; }
public string collectionArtistName { get; set; }
}
API folder - ItunesSearchAPI.cs:
using System.Globalization;
using System.Net;
using Newtonsoft.Json;
using ReachMobieItunesMVC.Models;
namespace ReachMobieItunesMVC.API;
public class ItunesSearchAPI
{
public static List<GroupedResult> Search(string Term)
{
try
{
//Making Web Request
ItunesSearchResults res = new ItunesSearchResults();
string BaseURL = "https://itunes.apple.com/search?term=";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(BaseURL + Term);
request.Method = "GET";
request.Headers.Add("cache-control", "no-cache");
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
request.ContentType = "application/json";
//Getting Response from Web Request
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string content = string.Empty;
using (Stream stream = response.GetResponseStream())
{
using (StreamReader sr = new StreamReader(stream))
{
content = sr.ReadToEnd();
//Serializing the Response to Object.
res =JsonConvert.DeserializeObject<ItunesSearchResults>(content);
}
}
// To capitalize the group key.
TextInfo textInfo = Thread.CurrentThread.CurrentCulture.TextInfo;
return res.results
.GroupBy(t => t.kind == null ? t.wrapperType : t.kind)
.Select(t => new GroupedResult() { Type = textInfo.ToTitleCase(t.Key.ToString())+"s", results = t.ToList(), TotalCount = res.resultCount })
.ToList();
}
catch (Exception ex)
{
throw ex;
}
}
}
In my controller class I was looking around the web and found that people make a folder called DataAccess that contains files with extensions .tt and .edmx (which I believe has been replaced) and I think that is for database purposes. Is this necessary according to my requirements? I was under the assumption that a database wouldn't be needed as the data is all in the API and we are just pulling from it. However, I know that I need to display a count of clicks per result but am not sure what these file extensions are for and how to use them. Anyways, any assistance would be appreciated.
HomeController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace ItunesSearch.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.SearchCounts = new DataAccess.ItunesSearchDBEntities().SearchCounts.OrderByDescending(a => a.Count).Take(25).ToList();
return View();
}
[HttpGet]
public ActionResult Search(string Term)
{
try
{
var result = SearchAPI.ItunesAPI.Search(Term);
ViewBag.value = Term;
return View(result);
}
catch (Exception)
{
throw;
}
}
[HttpGet]
public ActionResult CountAndGO(string URL, string SearchTerm)
{
DataAccess.ItunesSearchDBEntities db = new DataAccess.ItunesSearchDBEntities();
//Finding the term in database.
var _term = db.SearchCounts.Where(a => a.Term == SearchTerm.ToLower()).FirstOrDefault();
if (_term != null)
{
//If term is present Count is added
_term.Count++;
db.Entry(_term).State = System.Data.EntityState.Modified;
}
else
{
//Term is saved in database
db.SearchCounts.Add(new DataAccess.SearchCount() { Term = SearchTerm.ToLower(), Count = 1 });
}
db.SaveChanges();
if (URL == null || URL == "")
return RedirectToAction("NoURL");
return Redirect(URL);
}
public ActionResult NoURL()
{
return View();
}
}
}
