DEV Community

Matt Dyor
Matt Dyor

Posted on • Edited on

3 1

Building an ASP.NET Core Web App from Scratch

Get Started

  • https://github.com/OdeToCode/OdeToFood
  • Start with an asp.net core web application in visual studio
  • Select web application (not web application mvc) with defaults
  • Add a asp-page to _Layout pointing to Restaurats/list
  • Create a folder for Restaurants
  • Add a Razor Page (empty) called List in the Restaurants folder

Adding a property to List

(think of this as model in MVC)

  • inside the class, type prop TAB TAB string TAB TAB Message that will leave you with public string Message { get; set; }
  • In appsettings.config add a "Message": "hello world"
  • Back in List type ctor TAB TAB (this will add a constructor)
  • Add IConfiguration to () and hit CTRL + . then enter and call the variable config (looks like public ListModel(IConfiguration config)
  • hit CTRL + . on config and select "create and assign field config"
  • in the OnGet() method add Message = config["Message"];

Options

If you want to be able to refresh your browser while debugging in asp.net core, you need to add this nuget package:

If you want to use code generators, powershell in to project directory:

  • dotnet tool install --global dotnet-aspnet-codegenerator
  • dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design -v 3.1
  • dotnet aspnet-codegenerator razorpage -h
  • dotnet aspnet-codegenerator razorpage List2 Empty -udl -outDir .\Pages\Restaurants

Add Model

  • Right Click Solution and Add Project
  • Choose Class Library (.net core)
  • Delete the created class and add your own class, call it Restaurant, make it public
  • Add a int Id, string Name, and String Location property
  • Add an Enum and use CTRL + . to put it into its own class file
public enum CuisineType
        {
            None, 
            Mexican, 
            Chinese
        }
Enter fullscreen mode Exit fullscreen mode
  • Add a property of type CuisineType
  • CTRL+K then CTRL+D to format

Add Data Access

  • Add another library class
  • Delete the class and add an interface
  • Add an Interface with a GetAll() method
  • Implement a public class based on the interface
  • Add a readonly list of restaurants
  • You need to add a reference to the Restaurant class project to this project, and then add a using statement so that the restaurants is available in the data class
  • Create a constructor that populates the list of restaurants
  • Implement GetAll method - need to add a reference to System.Linq to get the orderby to work

Add Singleton of the data access to startup

  • Add this to the startup page services.AddSingleton<IRestaurantData, InMemoryRestaurantData>();

Add Data to List

  • Add the IRestaurantData interface to the data list constructor
  • CTRL + . on IRestaurantData and add "create and assign field config" - should look something like this public ListModel(IConfiguration config, IRestaurantData restaurantData)

Add Search

  • Add a form with method=get and no action (will point to itself).
  • Include a input type=search name=searchTerm
  • include an i tag with a class="fa-search"
  • To get font awesome to work, you need to get a fontawesome.io url and add it to your URL; if you want autocomplete you need to right click on the project name > add > client side library > provider=unpkg, search for font awesome. Code is like <i class="fas fa-search"></i>
  • Replace the GetAll on the restaurants interface with a GetRestaurantByName
  • In the implementation method, specify that the name is a string name=null, meaning that if not provided no filtering.
  • Update the linq query to include a where string.IsNullOrEmpty(name) || r.Name.StartsWith(name) that includes all if no filter (remember this filter is currently case sensitive)
  • Change the OnGet method of List code behind to include Restaurants = restaurantData.GetRestaurantsByName(searchTerm); here the searchTerm is pulled from the Request based on the name of the input field

Show Searched For Term

  • Instead of pulling the searchTerm from the request, specify a property with a capital S SearchTerm and a BindProperty that means it will Bind when the request is received
[BindProperty(SupportsGet =true)]
public string SearchTerm { get; set; }
Enter fullscreen mode Exit fullscreen mode
  • Replace name and value on input form to asp-for="SearchTerm" <input type="search" class="form-control" asp-for="SearchTerm" />

Make a Details Page

  • Right Click Restaurants folder, Add, Razor Page (empty)
  • Add public Restaurant Restaurant { get; set; } to the PageModel
  • On the cshtml, you can now use @Model.Restaurant.Name
  • You can make embed the restaurantId in the url with page "{restaurantId:int}"

Make an Edit Page

  • Largely the same as Details, but sometimes you need to use @Model and sometimes not
<form method="post">
    <input type="hidden" asp-for="@Model.Restaurant.Id" />
    <div class="form-group">
        <label asp-for="@Model.Restaurant.Name"></label>
        <input asp-for="@Model.Restaurant.Name" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="@Model.Restaurant.Location"></label>
        <input asp-for="@Model.Restaurant.Location" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="@Model.Restaurant.Name"></label>
        <select class="form-control" asp-for="Restaurant.Cuisine" asp-items="Model.Cuisines" >
        </select>
    </div>
</form>
Enter fullscreen mode Exit fullscreen mode
  • In the PageModel, you need to pull in the IHTMLHelper
public class EditModel : PageModel
    {
        private readonly IRestaurantData restaurantData;
        private readonly IHtmlHelper htmlHelper;

        public  Restaurant Restaurant { get; set; }
        public IEnumerable<SelectListItem> Cuisines { get; set; }
        public EditModel(IRestaurantData restaurantData, IHtmlHelper htmlHelper)
        {
            this.restaurantData = restaurantData;
            this.htmlHelper = htmlHelper;
        }
        public IActionResult OnGet(int restaurantId)
        {
            Cuisines = htmlHelper.GetEnumSelectList<CuisineType>(); 
            Restaurant = restaurantData.GetById(restaurantId); 
            if (Restaurant == null)
            {
                RedirectToPage("./NotFound");
            }
            return Page(); 
        }
    }
Enter fullscreen mode Exit fullscreen mode

Connect to Local SQL

  • Add a connection string to localdb
"ConnectionStrings": {
    "OdeToFoodDb":  "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=OdeToFood;Integrated Security=True;"
  }
Enter fullscreen mode Exit fullscreen mode
  • Wire up the app settings via configure services using an options lambda expression:
            services.AddDbContextPool<OdeToFoodDbContext>(options => {
                options.UseSqlServer(Configuration.GetConnectionString("OdeToFoodDb")); 
            }); 

Enter fullscreen mode Exit fullscreen mode
  • Add a constructor to the DbContext that pulls in the options from the app settings:
public OdeToFoodDbContext(DbContextOptions<OdeToFoodDbContext> options) : base(options)
        {
        }
Enter fullscreen mode Exit fullscreen mode
  • Finally need to tell the .Data project to look at the base project for the options information dotnet ef dbcontext info -s ..\OdeToFood\OdeToFood.csproj

Add a Migration

  • in the CLI run dotnet ef migrations add initialcreate -s ..\OdeToFood\OdeToFood.csproj
  • then apply the migration dotnet ef database update -s ..\OdeToFood\OdeToFood.csproj

Implement Delete Functionality

  • Add a Delete function Restaurant Delete(int id);
  • CTRL+. on the InMemoryRestaurantData and select option to move to its own class file
  • in the new file, CTRL+. and select to implement interface (this will add the delete)
  • Add the delete code
       {
            var restaurant = restaurants.FirstOrDefault(r => r.Id == id); 
            if (restaurant != null)
            {
                restaurants.Remove(restaurant); 
            }
            return restaurant; 
        }
Enter fullscreen mode Exit fullscreen mode

Add the SQL

  • on the IRestaurantData file, type this:
    public class SqlRestaurantData : IRestaurantData
    {

    }
Enter fullscreen mode Exit fullscreen mode
  • CTRL+. and SqlRestaurantData and select option to move to its own file
  • in the new file, CTRL+. implement the interface

AWS Q Developer image

Your AI Code Assistant

Implement features, document your code, or refactor your projects.
Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay