Skip to content

hpatel292-seneca/ASP.NET-notes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 

Repository files navigation

ASP.NET-notes

Here are notes based on the key topics from Lecture 2.1 - Persisting Data for your revision:


Persisting Data (Week 2 Topics)

  1. Textbook Usage: The course emphasizes using view model classes over directly interacting with persistent storage (database) through controllers, unlike the textbook examples.

  2. Project Template: You will use a pre-configured database in upcoming weeks to build interactive web apps. Later, you'll learn to create your own data store.

  3. System Design and Architecture: The course follows a layered architecture:

    • Views interact with controllers.
    • Controllers use view model classes for data exchange.
    • Manager class handles business logic and data service operations.
    • Data store (local database) is accessed indirectly using Entity Framework (EF).

Persistent Data Storage

  1. App Data: Relational databases are used, stored in the App_Data folder. The connection is managed via the Web.config file using a connection string.

  2. Local vs. Host-Based Databases:

    • During development, a local instance of SQL Server (within Visual Studio) is used.
    • When deploying, a host-based SQL Server can be configured.

Entity Framework (EF)

  1. Object-Relational Mapper (ORM):

    • Entity Framework is used to map C# objects to database tables, simplifying database interactions.
    • The Data Context serves as the gateway to the data store and supports common operations (querying, adding, updating, deleting).
  2. Design Model Classes:

    • These classes represent the entities in the database (e.g., tables), where each property maps to a column in the table.

Manager Class

  1. Role:

    • The Manager class centralizes app and business logic. Controllers never directly interact with the database; they call Manager methods.
    • Methods in the Manager class can handle tasks like fetching data, adding records, etc.
  2. Layered Architecture:

    • Manager classes promote a safer and more structured coding style by isolating database operations from controllers and views.
    • Data passed between Manager methods and controllers is handled by view model classes.

View Model Classes

  1. Purpose:

    • View models are tailored for specific use cases and simplify interactions between the UI and the underlying data model.
    • They are customized to fit exactly what is needed for display, form population, or form submission.
  2. Advantages:

    • Increased flexibility in how data is presented and processed.
    • Enhances security by preventing direct interaction between user data and the data model.
  3. Typical Use Cases:

    • Add: To create new entities.
    • Base: For retrieving and displaying data.
    • Edit: To update existing records.

AutoMapper

  1. Role:

    • AutoMapper helps map between design model classes (data from the database) and view model classes.
    • It works based on conventions, mapping properties with matching names and types automatically.
  2. Usage:

    • In this course, you are required to use the instance-based API of AutoMapper, as using the static API will result in grading penalties.

Domain Models:

  • Definition: Domain models represent the core entities or objects in your application's business logic. These models directly map to the concepts or things in the problem domain (the real world or the business you are working with).
  • Purpose: Domain models are used to interact with the database and manage business rules. They often mirror the structure of your database tables in applications using ORM (Object-Relational Mapping) tools like Entity Framework.
  • Example:
    • If you are building an e-commerce application, domain models could include Product, Customer, Order, etc.
    • For instance, a Customer domain model might look like:
      public class Customer
      {
          public int Id { get; set; }
          public string Name { get; set; }
          public string Email { get; set; }
          public DateTime DateOfBirth { get; set; }
          public ICollection<Order> Orders { get; set; }
      }

View Models:

  • Definition: View models are data transfer objects (DTOs) designed specifically for the presentation layer (the user interface). They contain only the data that is needed for the UI, making them lighter and more focused compared to domain models.
  • Purpose: View models simplify the data that is sent to the front end (or received from the front end). They decouple the domain/business models from the user interface, ensuring that sensitive data (e.g., passwords) or unnecessary data (e.g., internal system information) is not exposed.
  • Example:
    • In the same e-commerce application, a view model could represent only the necessary data for displaying customer information on the UI. For instance, a CustomerBaseViewModel might only include basic information:
      public class CustomerBaseViewModel
      {
          public int Id { get; set; }
          public string Name { get; set; }
          public string Email { get; set; }
      }

Differences between Domain Models and View Models:

  1. Purpose:

    • Domain Models: Represent the structure of your business or database entities. They often include relationships between objects (e.g., a customer having multiple orders).
    • View Models: Simplified objects used for displaying data in the user interface. They may omit fields that are unnecessary for the UI or sensitive to business logic.
  2. Usage:

    • Domain Models: Used internally in your application's business logic or to interact with a database.
    • View Models: Used to transfer data between the controller and the view/UI. They are mapped from domain models but serve a presentation-specific purpose.
  3. Structure:

    • Domain Models: Can include all properties related to the business entity, including relationships (e.g., orders for a customer).
    • View Models: Typically contain only the information required by the view (e.g., a customer’s name and email but not their orders).

Yes, you're exactly right! The purpose of AutoMapper is to simplify the process of converting (or mapping) between domain models and view models (or other data transfer objects, DTOs). AutoMapper automates this process, avoiding the need to manually copy properties between these objects. Let me explain how this works step-by-step:

Purpose of AutoMapper:

AutoMapper is a library that helps you:

  1. Map domain models to view models (and vice versa).
  2. Automatically handle data transformation between objects that have similar or related structures.
  3. Reduce boilerplate code that you would otherwise write manually to transfer data from one model to another.

Typical Workflow with AutoMapper:

Here’s how AutoMapper fits into the flow:

  1. Domain Model and Data Fetching:

    • First, you fetch data from the database using a domain model. The domain model often has all the data, including relationships, detailed properties, and sensitive information that are part of the business logic.
    • Example:
      public class Customer
      {
          public int Id { get; set; }
          public string Name { get; set; }
          public string Email { get; set; }
          public string PasswordHash { get; set; }  // Sensitive data
          public ICollection<Order> Orders { get; set; }  // Relationships
      }
  2. Mapping Domain Model to View Model:

    • After fetching the domain model, you map it to a view model using AutoMapper.

    • The view model contains only the data needed for the UI, so you strip out unnecessary or sensitive fields (e.g., PasswordHash).

    • AutoMapper automates the mapping of fields with the same or similar names between the domain model and the view model.

    • Example of View Model:

      public class CustomerBaseViewModel
      {
          public int Id { get; set; }
          public string Name { get; set; }
          public string Email { get; set; }  // Only what UI needs
      }
    • AutoMapper setup:

      var config = new MapperConfiguration(cfg =>
      {
          cfg.CreateMap<Customer, CustomerBaseViewModel>();
      });
      var mapper = config.CreateMapper();
    • Using AutoMapper to map the domain model to the view model:

      var customerViewModels = mapper.Map<IEnumerable<Customer>, IEnumerable<CustomerBaseViewModel>>(customers);
  3. Displaying the View Model in the UI:

    • The view model is sent to the UI, and it only contains the data that the view needs (e.g., customer name, email). This ensures that sensitive or irrelevant data is not exposed to the front end.
  4. Receiving Input (Reverse Mapping):

    • When the user submits a form (e.g., adding or editing a customer), the input data is often sent as a view model (such as CustomerAddViewModel).

    • You then use AutoMapper to map the view model back to the domain model.

    • Example:

      var newCustomer = mapper.Map<CustomerAddViewModel, Customer>(customerAddViewModel);
    • You can then use the newCustomer object to save it in the database.

Key Benefits of AutoMapper:

  1. Reduces Boilerplate Code: Without AutoMapper, you'd have to manually map each property from the domain model to the view model and vice versa. AutoMapper handles this for you, making the code cleaner and easier to maintain.

    • Example of manual mapping without AutoMapper:
      var customerViewModel = new CustomerBaseViewModel
      {
          Id = customer.Id,
          Name = customer.Name,
          Email = customer.Email
      };
  2. Consistent and Maintainable: AutoMapper ensures that mappings are handled consistently across your application. If your model changes (e.g., you add or remove properties), you only need to update the mappings in one place.

  3. Separation of Concerns: The domain model remains focused on the business logic and data storage, while the view model is optimized for displaying data in the UI. AutoMapper bridges these two models seamlessly.

Summary:

  • Domain Models represent all the data fetched from the database, including sensitive and detailed information.
  • View Models contain only the necessary information required for the UI, making the data lighter and more secure.
  • AutoMapper automatically maps domain models to view models and vice versa, saving you from writing repetitive code and ensuring that only the required data is sent to the front end.

In short, AutoMapper helps you extract only the needed data from your domain model and pass it to the view in a clean and efficient way.

Customer Index View

This Customer/Index.cshtml code is the Razor view for displaying a list of customers in a table format. Here’s a breakdown of the key components:

Model Declaration

@model IEnumerable<MyFirstWebApp.Models.CustomerBaseViewModel>
  • This line declares the type of the model the view will work with. In this case, the view expects a collection of CustomerBaseViewModel objects (which is likely passed from the controller).

HTML and Razor Syntax

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
  • Displays an "Index" header.
  • The @Html.ActionLink("Create New", "Create") generates a hyperlink that points to the Create action method in the controller. It allows users to navigate to a page for creating a new customer.

Table Setup

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.FirstName)
        </th>
        <!-- More columns here -->
    </tr>
  • A table is used to display customer information.
  • @Html.DisplayNameFor(...) renders the display name for each property (like FirstName, LastName, etc.), based on what is defined in the CustomerBaseViewModel class.

Rendering Customer Data

@foreach (var item in Model)
{
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.FirstName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.LastName)
        </td>
        <!-- More columns here -->
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.CustomerId }) |
            @Html.ActionLink("Details", "Details", new { id=item.CustomerId }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.CustomerId })
        </td>
    </tr>
}
  • @foreach (var item in Model) iterates over the collection of customers (Model) passed to the view.
  • Inside the loop, each customer (item) is displayed row by row.
  • @Html.DisplayFor(...) renders the value of each property for the current customer (item), like FirstName, LastName, etc.

Action Links

@Html.ActionLink("Edit", "Edit", new { id=item.CustomerId }) |
@Html.ActionLink("Details", "Details", new { id=item.CustomerId }) |
@Html.ActionLink("Delete", "Delete", new { id=item.CustomerId })
  • These are links that let the user interact with each customer:
    • Edit: Takes the user to the Edit action method for the specific customer, identified by CustomerId.
    • Details: Takes the user to the Details action method to view details for that customer.
    • Delete: Takes the user to the Delete action method to delete the customer.

Each of these action links passes the CustomerId as a route parameter to the corresponding action method in the controller.

Summary

  • This Razor view:
    • Displays a table with customer information.
    • Uses Html.DisplayNameFor to display the column names.
    • Uses Html.DisplayFor to show the values for each customer in the list.
    • Provides "Edit", "Details", and "Delete" actions for each customer.

Let me know if you'd like any further clarification!

In an ASP.NET project, using Scaffolding is a way to automatically generate code for common CRUD (Create, Read, Update, Delete) operations, views, and controllers based on the data models you have defined in your project. It helps developers save time by creating the necessary files and structures instead of writing everything manually.

Specifically, when you scaffold a view in an ASP.NET project, the Scaffolding tool will:

  1. Analyze the model: It looks at your data model (e.g., a class that represents a table in a database).
  2. Generate HTML and Razor code: It automatically creates a .cshtml file, which includes the necessary Razor syntax and HTML to display or manage the model’s data in the view.
  3. Generate CRUD views: If you're using Entity Framework, scaffolding can generate views like:
    • Create.cshtml: For creating new records.
    • Edit.cshtml: For updating records.
    • Delete.cshtml: For deleting records.
    • Details.cshtml: For viewing individual record details.
    • Index.cshtml: For listing records.

Steps to scaffold a view in ASP.NET:

  1. Right-click on the Controllers folder or the Views folder.
  2. Select Add > New Scaffolded Item.
  3. Choose the type of scaffold, such as MVC View Page, Controller with Views using Entity Framework, etc.
  4. Select the model and data context to generate the view based on that model.

Scaffolding speeds up the development process and ensures consistent code structure across your project.

Here’s a basic explanation and usage of DbContext and DbSet in an ASP.NET Core or Entity Framework Core project:

1. DbContext:

  • DbContext is a class in Entity Framework that represents a session with the database. It allows you to interact with your database by querying, saving, and performing other database-related operations.
  • It manages the entity objects during runtime and handles their state changes, allowing you to commit them to the database.

2. DbSet:

  • DbSet represents a collection of entities of a specific type (usually corresponding to a database table). It provides methods for querying and working with the entities (such as adding, removing, updating, etc.).

Example Use Case:

Let's say you have a simple Product entity, and you want to perform basic CRUD operations using DbContext and DbSet.

1. Define the Product Model (Entity)

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

2. Define Your DbContext

You’ll create a class that inherits from DbContext. Inside it, you define properties of type DbSet<T> for each entity type you want to work with (in this case, Product).

using Microsoft.EntityFrameworkCore;

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) 
        : base(options)
    {
    }

    // DbSet for the Product entity
    public DbSet<Product> Products { get; set; }

    // Additional DbSets for other entities can be added here.
}

3. Register the DbContext in Startup.cs (for ASP.NET Core)

In ASP.NET Core, you need to register ApplicationDbContext in the Startup.cs file or Program.cs file.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
        
        // Other services...
    }

    // Other methods...
}

4. Basic CRUD Operations with DbContext and DbSet

Now, in a controller or service class, you can use ApplicationDbContext to interact with the database.

public class ProductService
{
    private readonly ApplicationDbContext _context;

    public ProductService(ApplicationDbContext context)
    {
        _context = context;
    }

    // Add a new Product
    public async Task AddProduct(Product product)
    {
        _context.Products.Add(product);  // Adds the new product to the DbSet
        await _context.SaveChangesAsync();  // Commits the changes to the database
    }

    // Get all Products
    public async Task<List<Product>> GetProducts()
    {
        return await _context.Products.ToListAsync();  // Returns the list of products
    }

    // Get a Product by ID
    public async Task<Product> GetProductById(int id)
    {
        return await _context.Products.FindAsync(id);  // Finds the product by its primary key (Id)
    }

    // Update a Product
    public async Task UpdateProduct(Product product)
    {
        _context.Products.Update(product);  // Marks the product as modified
        await _context.SaveChangesAsync();  // Commits the changes
    }

    // Delete a Product
    public async Task DeleteProduct(int id)
    {
        var product = await _context.Products.FindAsync(id);  // Find the product by Id
        if (product != null)
        {
            _context.Products.Remove(product);  // Removes the product
            await _context.SaveChangesAsync();  // Commits the deletion
        }
    }
}

Key Points:

  • DbContext: Represents a session with the database, holds configurations and manages entity states.
  • DbSet: Represents a collection (table) of a specific entity type (e.g., Product) and provides methods to query, add, update, and delete records from the database.

This basic setup shows how to work with DbContext and DbSet to perform database operations in an ASP.NET project.

In the provided code:

ds.Entry(obj).CurrentValues.SetValues(customer);

Here’s a breakdown of how it works:

  1. ds.Entry(obj):

    • The ds is likely your Entity Framework DbContext (data context).
    • The Entry(obj) method retrieves the EntityEntry for the given object obj. This entry provides access to metadata and state information about the entity obj in the context. It allows you to work with that entity, which exists in the context’s in-memory representation.
  2. CurrentValues:

    • After retrieving the entity obj, you access its CurrentValues.
    • CurrentValues is a property of the EntityEntry and represents the current values of the entity's properties as a collection of DbPropertyValues. These values reflect the current state of the entity within the context.
  3. SetValues(customer):

    • This method sets or updates the current values of the entity (obj) with the values from the provided customer object.
    • It maps matching properties by name between obj and customer. If a property in customer matches a property in obj, the value from customer will overwrite the value in obj.
    • It ignores navigation properties (i.e., relationships) and only updates scalar properties (like strings, integers, etc.).
    • Any properties in customer that don’t exist in obj are ignored.

Usage:

  • This pattern is helpful when you want to update an entity’s properties without manually assigning each property one by one.
  • It’s particularly useful in scenarios like editing an existing record in a database using Entity Framework, where you load an entity (e.g., obj), then apply changes from a model or another object (e.g., customer), and finally save those changes back to the database.

Summary:

SetValues(customer) provides an efficient way to update an entity in the database by copying matching property values from another object (in this case, customer), while ignoring properties that don’t exist or navigation properties that represent relationships.

Data annotation in ASP.NET is a way to apply validation rules, display formatting, and model behavior by using attributes directly in the model classes. These attributes help ensure that the data meets certain requirements before being processed or saved to a database. They are part of the System.ComponentModel.DataAnnotations namespace.

Common Data Annotation Attributes:

  1. [Required]: Ensures the property must have a value.
  2. [StringLength]: Specifies the maximum and/or minimum length of a string.
  3. [Range]: Restricts a value to a specific numeric range.
  4. [RegularExpression]: Validates the property against a specific regular expression pattern.
  5. [EmailAddress]: Validates that the property contains a valid email address.
  6. [DisplayName]: Sets a custom display name for a property in UI.
  7. [Compare]: Compares two properties to ensure they have the same value.

Benefits of Data Annotations:

  1. Simplifies Validation: You can define validation rules directly in the model, ensuring that validation is centralized and consistent.
  2. Improves Code Readability: Attributes provide an easy-to-read, declarative way to enforce business rules and data integrity.
  3. Reduces Boilerplate Code: Eliminates the need for repetitive validation logic in the controller or service layer.
  4. Integrates with Client-Side Validation: When used with frameworks like ASP.NET MVC, it can automatically apply validation rules to the client side.
  5. Easy Error Handling: Validation attributes automatically generate user-friendly error messages when rules are violated.

LINQ (Language Integrated Query) is a powerful feature in .NET that allows developers to query data from various sources (such as collections, databases, XML, or even web services) in a consistent and readable way, using syntax integrated directly into C# or VB.NET. It simplifies data manipulation by offering a declarative approach to working with data structures like arrays, lists, and other collections.

Key Components of LINQ:

  1. Query Syntax: Resembles SQL-like syntax for querying data.
  2. Method Syntax: Uses methods like Where, Select, OrderBy, etc., available as extension methods.
  3. Deferred Execution: LINQ queries are not executed until the results are iterated, offering optimization.

Common Use Cases of LINQ in .NET Applications:

  1. Querying Collections (LINQ to Objects):

    • LINQ allows querying and manipulating in-memory collections (e.g., arrays, lists).
    • Example:
      var numbers = new List<int> { 1, 2, 3, 4, 5 };
      var evenNumbers = from num in numbers
                        where num % 2 == 0
                        select num;
  2. Database Operations (LINQ to SQL / Entity Framework):

    • LINQ can be used to query relational databases in a strongly-typed manner, providing compile-time checking and IntelliSense support.
    • Example:
      var employees = from emp in context.Employees
                      where emp.Department == "HR"
                      select emp;
  3. XML Querying (LINQ to XML):

    • LINQ enables querying and manipulating XML documents in an intuitive manner.
    • Example:
      var xml = XDocument.Load("file.xml");
      var elements = from elem in xml.Descendants("Item")
                     where (int)elem.Element("Price") > 100
                     select elem;
  4. Data Transformation:

    • LINQ is effective in transforming data from one format to another using Select, GroupBy, OrderBy, etc.
    • Example:
      var employees = new List<Employee>();
      var names = employees.Select(e => new { e.FirstName, e.LastName });
  5. Parallel LINQ (PLINQ):

    • With PLINQ, LINQ queries can be parallelized to improve performance on multi-core systems.
    • Example:
      var largeCollection = Enumerable.Range(1, 1000000);
      var evenNumbers = largeCollection.AsParallel().Where(n => n % 2 == 0);

LINQ enhances readability, reduces code complexity, and provides a unified way to work with different types of data sources in .NET applications.

Fluent Query Expression Syntax refers to a style of writing queries in LINQ using method chaining, which allows for more fluent and readable code. This syntax is often called Method Syntax in LINQ, and it contrasts with Query Syntax, which resembles SQL-like expressions.

In Fluent Syntax, you invoke methods provided by LINQ (like Where, Select, OrderBy) as extension methods on collections (e.g., IEnumerable<T>, IQueryable<T>). Each method call returns an updated collection or queryable object, allowing for chaining multiple methods in a readable sequence.

Example of Fluent Query Expression Syntax

var numbers = new List<int> { 1, 2, 3, 4, 5, 6 };

// Fluent Syntax to filter even numbers and sort them in descending order
var result = numbers.Where(n => n % 2 == 0)
                    .OrderByDescending(n => n);

Key Features of Fluent Syntax

  1. Method Chaining: Each LINQ method is called on the result of the previous one, producing a fluent chain.
  2. Extension Methods: LINQ methods are implemented as extension methods, allowing them to be called directly on collections.
  3. Deferred Execution: The query is not executed until the result is iterated (e.g., with a foreach loop).

Common Fluent Methods:

  • Where: Filters elements based on a condition.
  • Select: Projects each element into a new form.
  • OrderBy, OrderByDescending: Orders the elements in ascending or descending order.
  • GroupBy: Groups elements by a specified key.
  • Join: Joins two collections based on keys.
  • Take, Skip: Limits or skips elements in the collection.

Fluent Syntax vs. Query Syntax

  • Fluent (Method) Syntax:

    var evenNumbers = numbers.Where(n => n % 2 == 0)
                             .OrderByDescending(n => n);
  • Query Syntax:

    var evenNumbers = from n in numbers
                      where n % 2 == 0
                      orderby n descending
                      select n;

In a .NET Core MVC web app using Entity Framework (EF), associated data typically refers to the relationships between entities in your database, such as one-to-many, many-to-many, or one-to-one relationships. Here's how it works:

  1. Defining Relationships in Models: In your models, you define relationships between entities using navigation properties and data annotations or Fluent API to specify foreign keys and constraints.

    • One-to-Many:

      public class Category
      {
          public int CategoryId { get; set; }
          public string Name { get; set; }
          public List<Product> Products { get; set; }
      }
      
      public class Product
      {
          public int ProductId { get; set; }
          public string Name { get; set; }
          public int CategoryId { get; set; }  // Foreign Key
          public Category Category { get; set; }  // Navigation Property
      }
    • Many-to-Many (with a join entity):

      public class Student
      {
          public int StudentId { get; set; }
          public string Name { get; set; }
          public List<StudentCourse> StudentCourses { get; set; }
      }
      
      public class Course
      {
          public int CourseId { get; set; }
          public string Title { get; set; }
          public List<StudentCourse> StudentCourses { get; set; }
      }
      
      public class StudentCourse
      {
          public int StudentId { get; set; }
          public Student Student { get; set; }
      
          public int CourseId { get; set; }
          public Course Course { get; set; }
      }
  2. Configuring Relationships: You can configure relationships using Fluent API in the OnModelCreating method of your DbContext:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>()
            .HasOne(p => p.Category)
            .WithMany(c => c.Products)
            .HasForeignKey(p => p.CategoryId);
    
        modelBuilder.Entity<StudentCourse>()
            .HasKey(sc => new { sc.StudentId, sc.CourseId });
    }
  3. CRUD Operations: When working with associated data, EF Core automatically manages the relationships. For example, when adding a new product to a category, the foreign key will be set automatically:

    var category = _context.Categories.First();
    var product = new Product { Name = "New Product", Category = category };
    _context.Products.Add(product);
    _context.SaveChanges();
  4. Eager Loading and Lazy Loading: When retrieving associated data, you can use eager loading to load related entities in the same query using Include:

    var productsWithCategories = _context.Products
                                         .Include(p => p.Category)
                                         .ToList();

    Or use lazy loading, where related entities are loaded only when accessed, if lazy loading proxies are configured.

  5. View Models for Associated Data: In your MVC views, you can use view models to combine related data to present it in the UI:

    public class ProductViewModel
    {
        public string ProductName { get; set; }
        public string CategoryName { get; set; }
    }

This is a basic overview of how associated data works in a .NET Core MVC app with EF Core. While Query Syntax is often easier to read for complex queries (especially for SQL-like operations), Fluent Syntax is more flexible, supports method chaining, and is the only way to express some operations (like Skip, Take, or certain joins). Both syntaxes are interchangeable, and they often produce the same underlying query.


Simplified Notes on Associated Data in ASP.NET

Filtering and Associated Objects

  • When fetching a Program object that has associated data (like Subject), it doesn't include related objects by default.
  • To include associated data, you need to explicitly use eager loading by calling the Include() method.

Example of Filtering and Including Associated Objects

  • First, include the associated Subject data using Include():
    var progs = ds.Programs.Include("Subjects");
  • Then, add filtering to only include Program objects where Credential is "Degree":
    var progs = ds.Programs.Include("Subjects").Where(p => p.Credential == "Degree");

Filtering and Sorting with Associated Objects

  • You can chain Include(), Where(), and OrderBy() to filter and sort the data:
    var progs = ds.Programs
        .Include("Subjects")
        .Where(p => p.Credential == "Degree")
        .OrderBy(p => p.Code);
  • This retrieves Program objects with the "Degree" credential, includes their associated Subject objects, and sorts them by Code.

Suggested Query Strategies for Web Apps

  • Get all: Avoid using Include() in "get all" queries because it can result in fetching too much data. If necessary, limit the data using Take().
  • Get one: It’s common to use Include() in "get one" queries because the included data often adds value.

Lazy Loading vs Eager Loading

  • Lazy Loading: Fetches associated data only when accessed later. No Include() is needed.
  • Eager Loading: Fetches the object and its associated data all at once using Include().

Avoid Lazy Loading in Web Apps

  • Lazy Loading is not recommended for web apps because web apps use the HTTP protocol, where each request-response cycle is stateless.
  • Always use Eager Loading (Include()) in web apps to ensure all necessary data is fetched at once.

Lazy loading is ineffective in web apps and can cause issues, so it's best to disable it.

Previously Covered

  • Scaffolding a view: Generates views for common actions like list, create, edit, etc.
  • HTML Helpers: Help render HTML elements easily in Razor views.
  • Associated entities: Displaying related entities in views.

Item Selection and Bootstrap Overview

  • Item-selection elements are necessary when dealing with associated entities (e.g., dropdowns, checkboxes).
  • We will also explore Bootstrap for styling and responsive design in ASP.NET MVC.

Display-only Views

  • Scaffolding works well for display-only views, rendering objects in tables or description lists.
  • When dealing with associated entities, scaffolding does not render related objects; you need to use item-selection controls like dropdowns or checkboxes.

Data Modification Views

  • Scaffolding can generate input fields for adding, editing, and deleting data but does not handle item-selection elements like dropdowns or checkboxes.

Scaffolded HTML Form Elements:

HTML Form Element Scaffolded?
Label Yes
Text box Yes
Multiline text area Yes
Button Yes
Hidden field Yes
Dropdown list No
Listbox No
Radio button group No
Checkbox group No

Item-selection Elements in HTML Forms

  • Dropdown list:
    <select>
      <option>Option 1</option>
      <option>Option 2</option>
    </select>
  • Listbox (Single/Multiple Selection): Allows multiple selections with the multiple attribute:
    <select size="4" multiple>
      <option>Option 1</option>
      <option>Option 2</option>
    </select>
  • Radio buttons and Checkbox groups: Allow for single or multiple selections:
    <input type="radio" name="option" />
    <input type="checkbox" name="option" />

Hand-editing Item-selection Elements

  • Since scaffolding doesn’t generate item-selection elements, you’ll need to hand-code these elements into your views.
  • Strategy:
    1. Use scaffolding to generate base views.
    2. Edit the view code to add item-selection elements manually.

Passing Data to Item-selection Elements

  • Best practice: Create a view model that includes properties for the data required in item-selection elements.
  • View Models: Separate models for “add” and “edit” scenarios are recommended.
    • Example: VenueEditFormViewModel and VenueEditViewModel for form input and submission data.

Submitting Item-selection Data

  • For single-selection: The name attribute in HTML must match a property in the view model (usually an int or string).
  • For multiple-selection: The property in the view model should be a collection (e.g., List<int> or IEnumerable<int>).

Introduction to Bootstrap

  • Bootstrap is a popular framework for responsive and mobile-friendly web apps. It comes pre-installed with ASP.NET MVC.
  • Bootstrap 3.x is included by default, but the latest version is 5.x (don’t update it for course assignments due to compatibility).

How to Use Bootstrap

  • Bootstrap is primarily CSS-based. You use it by adding class names to HTML elements:
    • Grid system for layout.
    • Forms for styling input elements.
    • Tables for displaying data.
    • Buttons for actions.

Responsive Grid System

  • Bootstrap uses a 12-column grid system to create layouts that automatically adjust for different screen sizes.

Example of Grid Classes:

  • .col-xs-*: Extra small devices.
  • .col-sm-*: Small devices.
  • .col-md-*: Medium devices.
  • .col-lg-*: Large devices.

Bootstrap and HTML Forms

  • Wrap form controls in .form-group and use .form-control to get consistent, well-spaced, and styled forms.
  • Always pair <label> elements with form controls to ensure accessibility and proper alignment.

SelectList Introduction

  • SelectList is a class that helps package data for use in item-selection elements (e.g., dropdown lists).
  • Best practice: Add "List" as a suffix for SelectList properties in the view model (e.g., ManufacturerList).

Example:

public SelectList ManufacturerList { get; set; }

SelectList Constructor:

  1. IEnumerable items: The collection of items (e.g., Products, Employees).
  2. dataValueField: The property used for the "value" attribute (e.g., Id).
  3. dataTextField: The property used for the visible text (e.g., Name).

Using HTML Helpers

  • HTML Helpers make writing HTML simpler and integrate well with model binding.
  • Common HTML Helpers for item-selection elements:
    • @Html.DropDownList()
    • @Html.ListBox()

Example:

@Html.DropDownList("ManufacturerId", Model.ManufacturerList, new { @class = "form-control" })
  • Use these helpers for generating dropdowns and listboxes, but you’ll need to hand-code radio button and checkbox groups.

Conclusion

  • Bootstrap helps make your web apps responsive and visually consistent.
  • Item-selection elements (dropdowns, checkboxes) require hand-coding and integrating data through view models.
  • SelectList is crucial for creating dynamic item-selection elements.
  • HTML Helpers simplify form creation and help maintain a strong connection between the view and model data.

By following these practices, you can efficiently manage item-selection elements and improve the user experience with Bootstrap.


Handling the "POST" Method

  • The POST method is used to handle form data submitted by the user.
  • It works similarly to other "add new" use cases.
  • The difference here is that the PRG (Post-Redirect-Get) pattern is used, where after adding a new item, the user is redirected to the Details view in the VehiclesController.

Introduction to Attribute Routing

  • In traditional routing, URLs might look like this:
    https://host.example.com/manufacturers/addvehicle/56

    • This URL structure suggests that you’re adding a vehicle with an ID of 56, but the context might not be clear.
  • With Attribute Routing, you can make the URL more intuitive, such as:
    https://host.example.com/manufacturers/56/addvehicle

    • This URL clearly indicates adding a vehicle to manufacturer 56.

Creating Routes Using Attributes

  • Attribute Routing allows you to directly define routes in your controller actions.
  • For example, in ManufacturersController, you can specify the following route for adding a vehicle:
    [Route("manufacturers/{id}/addvehicle")]
    public ActionResult AddVehicle(int? id)

Enabling Attribute Routing

  • To use Attribute Routing, you need to enable it in your ASP.NET MVC app.
  • This is done by adding the following line to the RegisterRoutes method in RouteConfig:
    routes.MapMvcAttributeRoutes();
  • Attribute Routing can work alongside the conventional routing methods and provides more flexibility in defining custom resource URLs.

By using attribute routing, you can create more readable and meaningful URLs that clearly reflect the resource being accessed or the operation being performed, making your web app's navigation more intuitive.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published