Pro ASP NET MVC 3 framework, 3rd edition

837 246 0
Pro ASP NET MVC 3 framework, 3rd edition

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

www.it-ebooks.info For your convenience Apress has placed some of the front matter material after the index Please use the Bookmarks and Contents at a Glance links to access them www.it-ebooks.info Contents at a Glance ■About the Authors xxiii ■About the Technical Reviewer xxiv ■Acknowledgments xxv ■Part 1: Introducing ASP.NET MVC ■Chapter 1: What’s the Big Idea? ■Chapter 2: Getting Ready 17 ■Chapter 3: Your First MVC Application 31 ■Chapter 4: The MVC Pattern 63 ■Chapter 5: Essential Language Features 89 ■Chapter 6: Essential Tools for MVC 125 ■Chapter 7: SportsStore: A Real Application 155 ■Chapter 8: SportsStore: Navigation and Cart 195 ■Chapter 9: SportsStore: Administration 249 ■Part 2: ASP.NET MVC in Detail 301 ■Chapter 10: Overview of MVC Projects 303 ■Chapter 11: URLs, Routing, and Areas 325 ■Chapter 12: Controllers and Actions 385 ■Chapter 13: Filters 427 ■Chapter 14: Controller Extensibility .461 ■Chapter 15: Views 493 iv www.it-ebooks.info ■Chapter 16: Model Templates 543 ■Chapter 17: Model Binding 577 ■Chapter 18: Model Validation 601 ■Chapter 19: Unobtrusive Ajax 647 ■Chapter 20: jQuery 673 ■Part 3: Delivering Successful ASP.NET MVC Projects 709 ■Chapter 21: Security and Vulnerability 711 ■Chapter 22: Authentication and Authorization 731 ■Chapter 23: Deployment 761 ■Index 793 v v www.it-ebooks.info PART I ■■■ Introducing ASP.NET MVC ASP.NET MVC Framework is a radical shift for web developers using the Microsoft platform It emphasizes clean architecture, design patterns, and testability, and it doesn’t try to conceal how the Web works The first part of this book is designed to help you understand the foundational ideas of the ASP.NET MVC Framework, including the new features in ASP.NET MVC 3, and to experience in practice what the framework is like to use www.it-ebooks.info CHAPTER ■■■ What’s the Big Idea? ASP.NET MVC is a web development framework from Microsoft that combines the effectiveness and tidiness of model-view-controller (MVC) architecture, the most up-to-date ideas and techniques from agile development, and the best parts of the existing ASP.NET platform It’s a complete alternative to traditional ASP.NET Web Forms, delivering considerable advantages for all but the most trivial of web development projects In this chapter, you’ll learn why Microsoft originally created ASP.NET MVC, how it compares to its predecessors and alternatives, and finally, what’s new in ASP.NET MVC A Brief History of Web Development To understand the distinctive aspects and design goals of ASP.NET MVC, it’s worth considering the history of web development so far—brief though it may be Over the years, Microsoft’s web development platforms have demonstrated increasing power, and unfortunately, increasing complexity As shown in Table 1-1, each new platform tackled the specific shortcomings of its predecessor Table 1-1 Microsoft’s Lineage of Web Development Technologies Period Technology Strengths Weaknesses Jurassic Common Gateway * Interface (CGI) Simple Runs outside the web server, so is resource-intensive (spawns a separate operating system process per request) Flexible Only option at the time Low-level Bronze age Microsoft Internet Database Connector (IDC) Runs inside web server Just a wrapper for SQL queries and templates for formatting result sets 1996 Active Server Pages (ASP) General purpose Interpreted at runtime Encourages “spaghetti code” Continued www.it-ebooks.info CHAPTER ■ WHAT’S THE BIG IDEA? Period Technology Strengths Weaknesses 2002/03 ASP.NET Web Forms 1.0/1.1 Compiled Heavy on bandwidth “Stateful” UI Ugly HTML Vast infrastructure Untestable Encourages objectoriented programming 2005 ASP.NET Web Forms 2.0 2007 ASP.NET AJAX 2008 ASP.NET Web Forms 3.5 2009 ASP.NET MVC 1.0 2010 ASP.NET MVC 2.0 ASP.NET Web Forms 4.0 2011 ASP.NET MVC 3.0 *CGI is a standard means of connecting a web server to an arbitrary executable program that returns dynamic content The specification is maintained by the National Center for Supercomputing Applications (NCSA) www.it-ebooks.info CHAPTER ■ WHAT’S THE BIG IDEA? Traditional ASP.NET Web Forms ASP.NET was a huge shift when it first arrived in 2002 Figure 1-1 illustrates Microsoft’s technology stack as it appeared then Figure 1-1 The ASP.NET Web Forms technology stack With Web Forms, Microsoft attempted to hide both HTTP (with its intrinsic statelessness) and HTML (which at the time was unfamiliar to many developers) by modeling the user interface (UI) as a hierarchy of server-side control objects Each control kept track of its own state across requests (using the View State facility), rendering itself as HTML when needed and automatically connecting client-side events (for example, a button click) with the corresponding server-side event handler code In effect, Web Forms is a giant abstraction layer designed to deliver a classic event-driven graphical user interface (GUI) over the Web The idea was to make web development feel just the same as Windows Forms development Developers no longer needed to work with a series of independent HTTP requests and responses; we could now think in terms of a stateful UI We could forget about the Web and its stateless nature, and instead build UIs using a drag-and-drop designer, and imagine—or at least pretend—that everything was happening on the server www.it-ebooks.info CHAPTER ■ WHAT’S THE BIG IDEA? What’s Wrong with ASP.NET Web Forms? Traditional ASP.NET Web Forms development was a great idea, but reality proved more complicated Over time, the use of Web Forms in real-world projects highlighted some shortcomings: • View State weight: The actual mechanism for maintaining state across requests (known as View State) results in large blocks of data being transferred between the client and server This data can reach hundreds of kilobytes in even modest web applications, and it goes back and forth with every request, frustrating site visitors with slower response times and increasing the bandwidth demands of the server • Page life cycle: The mechanism for connecting client-side events with server-side event handler code, part of the page life cycle, can be extraordinarily complicated and delicate Few developers have success manipulating the control hierarchy at runtime without getting View State errors or finding that some event handlers mysteriously fail to execute • False sense of separation of concerns: ASP.NET’s code-behind model provides a means to take application code out of its HTML markup and into a separate codebehind class This has been widely applauded for separating logic and presentation, but in reality, developers are encouraged to mix presentation code (for example, manipulating the server-side control tree) with their application logic (for example, manipulating database data) in these same monstrous codebehind classes The end result can be fragile and unintelligible • Limited control over HTML: Server controls render themselves as HTML, but not necessarily the HTML you want Prior to ASP.NET 4, the HTML output usually failed to comply with web standards or make good use of Cascading Style Sheets (CSS), and server controls generated unpredictable and complex ID values that are hard to access using JavaScript These problems are reduced in ASP.NET 4, but it can still be tricky to get the HTML you expect • Leaky abstraction: Web Forms tries to hide away HTML and HTTP wherever possible As you try to implement custom behaviors, you frequently fall out of the abstraction, which forces you to reverse-engineer the postback event mechanism or perform obtuse acts to make it generate the desired HTML Plus, all this abstraction can act as a frustrating barrier for competent web developers • Low testability: The designers of ASP.NET could not have anticipated that automated testing would become an essential component of software development Not surprisingly, the tightly coupled architecture they designed is unsuitable for unit testing Integration testing can be a challenge, too ASP.NET has kept moving Version 2.0 added a set of standard application components that can reduce the amount of code you need to write yourself The AJAX release in 2007 was Microsoft’s response to the Web 2.0/AJAX frenzy of the day, supporting rich client-side interactivity while keeping developers’ lives simple The most recent release, ASP.NET 4, produces more predictable and standardscompliant HTML markup, but many of the intrinsic limitations remain www.it-ebooks.info CHAPTER ■ WHAT’S THE BIG IDEA? Web Development Today Outside Microsoft, web development technology has been progressing rapidly and in several different directions since Web Forms was first released Aside from AJAX, there have been other major developments Web Standards and REST The drive for web standards compliance has increased in recent years Web sites are consumed on a greater variety of devices and browsers than ever before, and web standards (for HTML, CSS, JavaScript, and so forth) remain our one great hope for enjoying a decent browsing experience everywhere—even on the Internet-enabled refrigerator Modern web platforms can’t afford to ignore the business case and the weight of developer enthusiasm for web standards compliance At the same time, Representational State Transfer (REST) has become the dominant architecture for application interoperability over HTTP, completely overshadowing SOAP (the technology behind ASP.NET’s original approach to web services) REST describes an application in terms of resources (URIs) representing real-world entities and standard operations (HTTP methods) representing available operations on those resources For example, you might PUT a new http://www.example.com/ Products/Lawnmower or DELETE http://www.example.com/Customers/Arnold-Smith Today’s web applications don’t serve just HTML; often they must also serve JSON or XML data to various client technologies including AJAX, Silverlight, and native smartphone applications This happens naturally with REST, which eliminates the historical distinction between web services and web applications—but requires an approach to HTTP and URL handling that has not easily been supported by ASP.NET Web Forms Agile and Test-Driven Development It is not just web development that has moved on in the last decade—software development as a whole has shifted towards agile methodologies This can mean a lot of different things, but it is largely about running software projects as adaptable processes of discovery, resisting the encumbrance and restrictions of excessive forward planning Enthusiasm for agile methodologies tends to go hand-inhand with a particular set of development practices and tools (usually open source) that promote and assist these practices Test-driven development (TDD), and its latest incarnation, behavior-driven development (BDD), are two obvious examples The idea is to design your software by first describing examples of desired behaviors (known as tests or specifications), so at any time, you can verify the stability and correctness of your application by executing your suite of specifications against the implementation There’s no shortage of NET tools to support TDD/BDD, but these tend not to work well with Web Forms: • Unit testing tools let you specify the behavior of individual classes or other small code units in isolation These can be effectively applied only to software that has been designed as a set of independent modules, so that each test can be run in isolation Unfortunately, few Web Forms applications can be tested this way Following the framework’s guidance to put logic into event handlers or even use server controls that directly query databases, developers typically end up tightly coupling their own application logic to the Web Forms runtime environment This is death for unit testing www.it-ebooks.info ■ CONTENTS Improving the URLs 187 Styling the Content 188 Defining Common Content in the Layout 189 Adding CSS Rules 190 Creating a Partial View 191 Summary .194 ■Chapter 8: SportsStore: Navigation and Cart .195 Adding Navigation Controls 195 Filtering the Product List 195 Refining the URL Scheme 198 Building a Category Navigation Menu 201 Correcting the Page Count 210 Building the Shopping Cart 213 Defining the Cart Entity 213 Adding the Add to Cart Buttons 217 Implementing the Cart Controller 218 Displaying the Contents of the Cart 220 Using Model Binding 223 Creating a Custom Model Binder 224 Completing the Cart .228 Removing Items from the Cart 228 Adding the Cart Summary 230 Submitting Orders 233 Extending the Domain Model 233 Adding the Checkout Process 234 Implementing the Order Processor 238 Registering the Implementation 241 Completing the Cart Controller 241 xi xi www.it-ebooks.info ■ CONTENTS Displaying Validation Errors 245 Displaying a Summary Page 246 Summary .248 ■Chapter 9: SportsStore: Administration 249 Adding Catalog Management .249 Creating a CRUD Controller 250 Rendering a Grid of Products in the Repository 252 Creating a New Layout 253 Implementing the List View 255 Editing Products 260 Creating New Products 275 Deleting Products 276 Securing the Administration Features 279 Setting Up Forms Authentication 280 Applying Authorization with Filters 281 Creating the Authentication Provider 282 Creating the Account Controller 284 Creating the View 285 Image Uploads .290 Extending the Database 290 Enhancing the Domain Model 290 Updating the Entity Framework Conceptual Model 291 Creating the Upload User Interface Elements 292 Saving Images to the Database 293 Implementing the GetImage Action Method 294 Displaying Product Images 298 Summary .299 xii xii www.it-ebooks.info ■ CONTENTS ■Part 2: ASP.NET MVC in Detail 301 ■Chapter 10: Overview of MVC Projects 303 Working with Visual Studio MVC Projects 303 Using the Internet and Intranet Application Controllers 308 Understanding MVC Conventions 309 Debugging MVC Applications .310 Creating the Project 310 Launching the Visual Studio Debugger 311 Causing the Visual Studio Debugger to Break 312 Using Edit and Continue 317 Project-Wide Dependency Injection .321 Summary .323 ■Chapter 11: URLs, Routing, and Areas .325 Introducing the Routing System 325 Creating the Routing Project 326 Introducing URL Patterns 327 Creating and Registering a Simple Route 329 Defining Default Values 334 Using Static URL Segments 336 Defining Custom Segment Variables 340 Defining Optional URL Segments 342 Defining Variable-Length Routes 344 Prioritizing Controllers by Namespaces 346 Constraining Routes 349 Routing Requests for Disk Files 354 Bypassing the Routing System 357 Generating Outgoing URLs 358 Preparing the Project 358 xiii xiii www.it-ebooks.info ■ CONTENTS Generating Outgoing URLs in Views 359 Generating Outgoing URLs in Action Methods 366 Generating a URL from a Specific Route 367 Customizing the Routing System 368 Creating a Custom RouteBase Implementation 368 Creating a Custom Route Handler 373 Working with Areas 374 Creating an Area 375 Populating an Area 377 Resolving the Ambiguous Controller Issue 379 Generating Links to Actions in Areas 380 URL Schema Best Practices 381 Make Your URLs Clean and Human-Friendly 381 GET and POST: Pick the Right One 382 Summary .383 ■Chapter 12: Controllers and Actions 385 Introducing the Controller 385 Preparing the Project 385 Creating a Controller with IController 385 Creating a Controller by Deriving from the Controller Class 387 Receiving Input 389 Getting Data from Context Objects 389 Using Action Method Parameters 391 Producing Output 393 Understanding Action Results 395 Returning HTML by Rendering a View 399 Passing Data from an Action Method to a View 403 Performing Redirections 409 xiv xiv www.it-ebooks.info ■ CONTENTS Returning Text Data 414 Returning XML Data 416 Returning JSON Data 417 Returning Files and Binary Data 418 Returning Errors and HTTP Codes 421 Creating a Custom Action Result 423 Summary .426 ■Chapter 13: Filters .427 Using Filters 427 Introducing the Four Basic Types of Filters 429 Applying Filters to Controllers and Action Methods 430 Using Authorization Filters 431 Using Exception Filters 437 Using Action and Result Filters 442 Using Other Filter Features 448 Using the Built-in Filters 454 Summary .459 ■Chapter 14: Controller Extensibility 461 Request Processing Pipeline Components 461 Creating a Controller Factory .461 Defining a Custom Controller Factory 462 Registering a Custom Controller Factory 464 Working with the Built-In Controller Factory 464 Prioritizing Namespaces 465 Customizing DefaultControllerFactory Controller Creation 466 Creating a Custom Action Invoker 468 Using the Built-In Action Invoker 470 Using a Custom Action Name 470 xv xv www.it-ebooks.info ■ CONTENTS Using Action Method Selection 472 Using Action Method Selectors to Support REST Services 475 Improving Performance with Specialized Controllers 478 Using Sessionless Controllers 478 Using Asynchronous Controllers 480 Summary .491 ■Chapter 15: Views 493 Creating a Custom View Engine 493 Creating a Custom IView 495 Creating an IViewEngine Implementation 496 Registering a Custom View Engine 497 Working with the Razor Engine 500 Understanding Razor View Rendering 500 Adding Dependency Injection to Razor Views 502 Configuring the View Search Locations 503 Adding Dynamic Content to a Razor View 505 Using Inline Code 506 Using HTML Helpers .512 Creating an Inline HTML Helper 513 Creating an External Helper Method 514 Using the Built-in HTML Helpers 516 Using Sections .532 Testing For Sections 535 Rendering Optional Sections 535 Using Partial Views 536 Creating a Partial View 536 Using Strongly Typed Partial Views 537 Using Child Actions 539 xvi xvi www.it-ebooks.info ■ CONTENTS Creating a Child Action 540 Rendering a Child Action 540 Summary .541 ■Chapter 16: Model Templates 543 Using Templated View Helpers 543 Styling Generated HTML 548 Using Model Metadata 550 Working with Complex Type Parameters 559 Customizing the Templated View Helper System 561 Creating a Custom Editor Template 561 Creating a Custom Display Template 565 Creating a Generic Template 565 Replacing the Built-in Templates 566 Using the ViewData.TemplateInfo Property 568 Passing Additional Metadata to a Template 569 Understanding the Metadata Provider System 570 Creating a Custom Model Metadata Provider 571 Customizing the Data Annotations Model Metadata Provider 574 Summary .576 ■Chapter 17: Model Binding 577 Understanding Model Binding 577 Using the Default Model Binder .578 Binding to Simple Types 580 Binding to Complex Types 581 Binding to Arrays and Collections 585 Manually Invoking Model Binding 588 Restricting Binding to a Specific Data Source 589 Dealing with Binding Errors 590 xvii xvii www.it-ebooks.info ■ CONTENTS Using Model Binding to Receive File Uploads 591 Customizing the Model Binding System 592 Creating a Custom Value Provider 592 Creating a Dependency-Aware Model Binder 594 Creating a Custom Model Binder 595 Creating Model Binder Providers 598 Using the ModelBinder Attribute 599 Summary .599 ■Chapter 18: Model Validation 601 Creating the Project .601 Explicitly Validating a Model 604 Displaying Validation Messages 606 Displaying Property-Level Validation Messages 610 Using Alternative Validation Techniques 612 Performing Validation in the Model Binder 612 Specifying Validation Rules Using Metadata 616 Defining Self-validating Models 621 Creating a Custom Validation Provider 622 Performing Client-Side Validation 626 Enabling and Disabling Client-Side Validation 627 Using Client-Side Validation 629 Understanding How Client-Side Validation Works 634 Customizing Client-Side Validation 635 Performing Remote Validation .642 Summary .645 ■Chapter 19: Unobtrusive Ajax 647 Using MVC Unobtrusive Ajax 647 Creating the Project 647 xviii xviii www.it-ebooks.info ■ CONTENTS Enabling and Disabling Unobtrusive Ajax 650 Using Unobtrusive Ajax Forms 651 Understanding How Unobtrusive Ajax Works 653 Setting Ajax Options .654 Ensuring Graceful Degradation 654 Providing the User with Feedback While Making an Ajax Request 656 Prompting the User Before Making a Request 657 Creating Ajax Links 658 Ensuring Graceful Degradation for Links 661 Working with Ajax Callbacks 662 Working with JSON 665 Adding JSON Support to the Controller 666 Processing JSON in the Browser 668 Detecting Ajax Requests in the Action Method 669 Receiving JSON Data 670 Summary .672 ■Chapter 20: jQuery .673 Creating the Project .673 Referencing jQuery 675 Writing jQuery Code .678 Creating a jQuery Sandbox 679 Basic jQuery Theory .682 Understanding jQuery Selectors 683 Using jQuery Filters 686 Understanding jQuery Methods 688 Waiting for the DOM 689 Using jQuery CSS Methods 690 Working with the DOM 694 xix xix www.it-ebooks.info ■ CONTENTS Using jQuery Events .698 Using jQuery Visual Effects 699 Using jQuery UI 701 Referencing jQuery UI 702 Making Better Buttons 703 Using a Slider 704 Summary .708 ■Part 3: Delivering Successful ASP.NET MVC Projects 709 ■Chapter 21: Security and Vulnerability 711 All Input Can Be Forged 711 Forging HTTP Requests 713 Cross-Site Scripting and HTML Injection .715 Understanding an XSS Vulnerability 715 Razor HTML Encoding 716 Request Validation 717 JavaScript String Encoding and XSS 720 Session Hijacking 722 Defense via Client IP Address Checks 723 Defense by Setting the HttpOnly Flag on Cookies 723 Cross-Site Request Forgery 724 Attack 724 Defense 725 Preventing CSRF Using the Antiforgery Helpers 725 SQL Injection 727 Attack 727 Defense Using Parameterized Queries 728 Defense Using Object-Relational Mapping 728 Using the MVC Framework Securely .728 xx xx www.it-ebooks.info ■ CONTENTS Don’t Expose Action Methods Accidentally 728 Don’t Allow Model Binding to Change Sensitive Properties 729 Summary .730 ■Chapter 22: Authentication and Authorization 731 Using Windows Authentication 731 Using Forms Authentication 734 Setting Up Forms Authentication 735 Using Cookieless Forms Authentication 738 Using Membership, Roles, and Profiles 738 Setting Up and Using Membership 740 Setting Up and Using Roles 749 Setting Up and Using Profiles 753 Why You Shouldn’t Use URL-Based Authorization 758 Restricting Access Using IP Addresses and Domains 758 Summary .760 ■Chapter 23: Deployment 761 Preparing an Application for Deployment 761 Detecting View Errors Before Deployment 761 Configuring Dynamic Page Compilation 762 Preparing for a Bin Deployment 763 Preparing the Web.config File for Transformation 764 Preparing the Project for Database Deployment 776 Understanding the IIS Fundamentals 779 Understanding Web Sites 779 Understanding Virtual Directories 779 Understanding Application Pools 780 Binding Web Sites to Hostnames, IP Addresses, and Ports 780 Preparing the Server for Deployment 781 xxi xxi www.it-ebooks.info ■ CONTENTS Deploying an Application .783 Deploying an Application by Copying Files 784 Using a Deployment Package 785 Using One-Click Publishing 790 Summary .792 ■Index 793 xxii xxii www.it-ebooks.info About the Authors Adam Freeman is an experienced IT professional who has held senior positions in a range of companies, most recently serving as Chief Technology Officer and Chief Operating Officer of a global bank Now retired, he spends his time writing and training for his first competitive triathlon This is his eleventh book on programming and his ninth on NET Steven Sanderson works for Microsoft as a Program Manager in the Web Platform and Tools team, trying to make sure Microsoft web technologies are as useful as possible for developers He has experienced the life of a web developer in both international corporations and newborn startups, as well as being a regular author and speaker on the subject Outside work hours, he develops and maintains open source projects at http://github.com/SteveSanderson xxiii www.it-ebooks.info About the Technical Reviewer Fabio Claudio Ferracchiati is a senior consultant and a senior analyst/developer using Microsoft technologies He works for Brain Force (www.brainforce.com) in its Italian branch (www.brainforce.it) Fabio is a Microsoft Certified Solution Developer for NET, a Microsoft Certified Application Developer for NET, a Microsoft Certified Professional, and a prolific author and technical reviewer Over the past ten years, he has written articles for Italian and international magazines, and coauthored more than ten books on a variety of computer topics xxiv www.it-ebooks.info Acknowledgments We would like to thank everyone at Apress for working so hard to bring this book to print In particular, we would like to thank Jennifer Blackwell for keeping us on track and Ewan Buckingham for commissioning and editing this revision We would also like to thank our technical reviewer, Fabio Claudio Ferracchiati, whose efforts made this book far better than it would otherwise have been —Adam Freeman and Steve Sanderson xxv www.it-ebooks.info ... objectoriented programming 2005 ASP. NET Web Forms 2.0 2007 ASP. NET AJAX 2008 ASP. NET Web Forms 3. 5 2009 ASP. NET MVC 1.0 2010 ASP. NET MVC 2.0 ASP. NET Web Forms 4.0 2011 ASP. NET MVC 3. 0 *CGI is a... concepts in MVC The ASP. NET MVC Framework implements the MVC pattern, and in doing so, provides greatly improved separation of concerns In fact, ASP. NET MVC implements a modern variant of MVC that’s... ■Part 2: ASP. NET MVC in Detail 30 1 ■Chapter 10: Overview of MVC Projects 30 3 ■Chapter 11: URLs, Routing, and Areas 32 5 ■Chapter 12: Controllers and Actions 38 5 ■Chapter

Ngày đăng: 27/03/2019, 16:47

Mục lục

  • Cover

    • Contents at a Glance

    • Contents

    • About the Authors

    • About the Technical Reviewer

    • Acknowledgments

    • --- PART 1 --- Introducing ASP.NET MVC 3

    • Chapter 1: What’s the Big Idea?

      • A Brief History of Web Development

        • Traditional ASP.NET Web Forms

        • What’s Wrong with ASP.NET Web Forms?

        • Web Development Today

          • Web Standards and REST

          • Agile and Test-Driven Development

          • Ruby on Rails

          • Sinatra

          • Node.js

          • Key Benefits of ASP.NET MVC

            • MVC Architecture

            • Extensibility

            • Tight Control over HTML and HTTP

            • Testability

            • Powerful Routing System

            • Built on the Best Parts of the ASP.NET Platform

            • Modern API

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan