Skip to content

Commit

Permalink
start of search (#1457)
Browse files Browse the repository at this point in the history
* start of search

* finished search

* final
  • Loading branch information
Rick-Anderson committed Jun 24, 2016
1 parent cf3a12e commit affe6e9
Show file tree
Hide file tree
Showing 24 changed files with 744 additions and 203 deletions.
11 changes: 6 additions & 5 deletions aspnet/tutorials/first-mvc-app/adding-controller.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ We'll be covering all these concepts in this tutorial series and show you how to

.. image:: adding-controller/_static/mvc1.png

- In **Solution Explorer**, right-click **Controllers > Add > Controller...**
- In **Solution Explorer**, right-click **Controllers > Add > New Item...**

.. image:: adding-controller/_static/add_controller.png

Expand All @@ -35,7 +35,7 @@ Every ``public`` method in a controller is callable as an HTTP endpoint. In the
:dedent: 4
:emphasize-lines: 4,12

The first comment states this is an `HTTP GET <http://www.w3schools.com/tags/ref_httpmethods.asp>`__ method that is invoked by appending "/HelloWorld/" to the URL. The second comment specifies an `HTTP GET <http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html>`__ method that is invoked by appending "/HelloWorld/Welcome/" to the URL. Later on in the tutorial we'll use the scaffolding engine to generate ``HTTP POST`` methods.
The first comment states this is an `HTTP GET <http://www.w3schools.com/tags/ref_httpmethods.asp>`__ method that is invoked by appending "/HelloWorld/" to the base URL. The second comment specifies an `HTTP GET <http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html>`__ method that is invoked by appending "/HelloWorld/Welcome/" to the URL. Later on in the tutorial we'll use the scaffolding engine to generate ``HTTP POST`` methods.

Run the app in non-debug mode (press Ctrl+F5) and append "HelloWorld" to the path in the address bar. (In the image below, http://localhost:1234/HelloWorld is used, but you'll have to replace *1234* with the port number of your app.) The ``Index`` method returns a string. You told the system to return some HTML, and it did!

Expand All @@ -57,7 +57,7 @@ When you run the app and don't supply any URL segments, it defaults to the "Home

The first URL segment determines the controller class to run. So ``localhost:xxxx/HelloWorld`` maps to the ``HelloWorldController`` class. The second part of the URL segment determines the action method on the class. So ``localhost:xxxx/HelloWorld/Index`` would cause the ``Index`` method of the ``HelloWorldController`` class to run. Notice that we only had to browse to ``localhost:xxxx/HelloWorld`` and the ``Index`` method was called by default. This is because ``Index`` is the default method that will be called on a controller if a method name is not explicitly specified. The third part of the URL segment ( ``id``) is for route data. We'll see route data later on in this tutorial.

Browse to ``http://localhost:xxxx/HelloWorld/Welcome``. The ``Welcome`` method runs and returns the string "This is the Welcome action method...". The default MVC routing is ``/[Controller]/[ActionName]/[Parameters]``. For this URL, the controller is ``HelloWorld`` and ``Welcome`` is the action method. We haven't used the ``[Parameters]`` part of the URL yet.
Browse to ``http://localhost:xxxx/HelloWorld/Welcome``. The ``Welcome`` method runs and returns the string "This is the Welcome action method...". For this URL, the controller is ``HelloWorld`` and ``Welcome`` is the action method. We haven't used the ``[Parameters]`` part of the URL yet.

.. image:: adding-controller/_static/welcome.png

Expand All @@ -70,7 +70,7 @@ Let's modify the example slightly so that you can pass some parameter informatio

.. note:: The code above uses ``HtmlEncoder.Default.Encode`` to protect the app from malicious input (namely JavaScript). It also uses `Interpolated Strings <https://msdn.microsoft.com/en-us/library/dn961160.aspx>`__.

.. note:: In Visual Studio 2015, when you are running without debugging (Ctl+F5), you don't need to build the app after changing the code. Just save the file, refresh your browser and you can see the changes.
.. note:: In Visual Studio 2015, when you are running in IIS Express without debugging (Ctl+F5), you don't need to build the app after changing the code. Just save the file, refresh your browser and you can see the changes.

Run your app and browse to:

Expand All @@ -97,7 +97,8 @@ This time the third URL segment matched the route parameter ``id``. The ``Welco

.. literalinclude:: start-mvc/sample2/src/MvcMovie/Startup.cs
:language: c#
:lines: 80-85
:start-after: app.UseIdentity();
:end-before: SeedData.Initialize(app.ApplicationServices);
:dedent: 12
:emphasize-lines: 5

Expand Down
84 changes: 65 additions & 19 deletions aspnet/tutorials/first-mvc-app/adding-model.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Complete the **New Project** dialog:
In the **New ASP.NET Core Web Application - MvcMovie** dialog:

- tap **Web Application**
- tap the **Change Authentication** button and change the authentication to **Individual User Accounts** and tap **OK**
- tap the **Change Authentication** button and change the authentication to **Individual User Accounts** and tap **OK**

.. image:: start-mvc/_static/p4.png

Expand Down Expand Up @@ -95,9 +95,26 @@ We'll follow those instructions to get the database ready for our Movie app.
Update the database
-------------------------------------------

.. warning:: You must build the project before you run the ``dotnet ef --no-build`` commands.
.. warning:: You must stop IIS Express before you update the database.

.. To-do replace command prompt to PMC. It's the preferred approach, you don't need to leave VS
.. _stop-IIS-Express-reference-label:

To Stop IIS Express:
^^^^^^^^^^^^^^^^^^^^^

- Right click the IIS Express system tray icon in the notification area

.. image:: working-with-sql/_static/iisExIcon.png
:height: 100px
:width: 200 px

- Tap **Exit** or **Stop Site**

.. image:: working-with-sql/_static/stopIIS.png

- Alternatively, you can exit and restart Visual Studio

.. To-do replace command prompt to PMC. It's the preferred approach, you don't need to leave VS
- Open a command prompt in the project directory (MvcMovie/src/MvcMovie). Follow these instructions for a quick way to open a folder in the project directory.

Expand All @@ -107,15 +124,15 @@ Update the database
|
.. image:: adding-model/_static/quick.png

|
- Shift + right click a folder > **Open command window here**

|
.. image:: adding-model/_static/folder.png

|
- Run ``cd ..`` to move back up to the project directory
Expand All @@ -124,17 +141,16 @@ Update the database

.. code-block:: console
dotnet ef --no-build migrations add Initial
dotnet ef --no-build database update
dotnet ef migrations add Initial
dotnet ef database update
.. note:: If you don't use the "--no-build" option and IIS-Express is running, you'll get the error *CS2012: Cannot open 'MvcMovie/bin/Debug/netcoreapp1.0/MvcMovie.dll' for writing -- 'The process cannot access the file 'MvcMovie/bin/Debug/netcoreapp1.0/MvcMovie.dll' because it is being used by another process.'* - You can stop IIS-Express to avoid this error or use the "--no-build" option.
.. note:: If IIS-Express is running, you'll get the error *CS2012: Cannot open 'MvcMovie/bin/Debug/netcoreapp1.0/MvcMovie.dll' for writing -- 'The process cannot access the file 'MvcMovie/bin/Debug/netcoreapp1.0/MvcMovie.dll' because it is being used by another process.'*

dotnet ef commands
dotnet ef commands
^^^^^^^^^^^^^^^^^^^

- ``dotnet`` (.NET Core) is a cross-platform implementation of .NET. You can read about it `here <http://go.microsoft.com/fwlink/?LinkId=798644>`__
- ``dotnet ef --no-build <command>`` Tells EF not to build the project before running the command
- ``dotnet ef migrations add Initial`` Runs the Entity Framework .NET Core CLI migrations command and creates the initial migration. The parameter "Initial" is arbitrary, but customary for the first (*initial*) database migration. This operation creates the *Data/Migrations/2016<date-time>_Initial.cs* file containing the migration commands to add (or drop) the `Movie` table to the database
- ``dotnet ef migrations add Initial`` Runs the Entity Framework .NET Core CLI migrations command and creates the initial migration. The parameter "Initial" is arbitrary, but customary for the first (*initial*) database migration. This operation creates the *Data/Migrations/<date-time>_Initial.cs* file containing the migration commands to add (or drop) the `Movie` table to the database
- ``dotnet ef database update`` Updates the database with the migration we just created


Expand All @@ -150,6 +166,17 @@ Test the app

.. note:: You may not be able to enter decimal points or commas in the ``Price`` field. To support `jQuery validation <http://jqueryvalidation.org/>`__ for non-English locales that use a comma (",") for a decimal point, and non US-English date formats, you must take steps to globalize your app. See `Additional resources`_ for more information. For now, just enter whole numbers like 10.

.. _DisplayFormatDateLocal:

.. note:: In some locals you'll need to specify the date format. See the highlighted code below.

.. literalinclude:: start-mvc/sample2/src/MvcMovie/Models/MovieDateFormat.cs
:language: c#
:start-after: // Start
:end-before: */
:emphasize-lines: 10,2

Tapping **Create** causes the form to be posted to the server, where the movie information is saved in a database. You are then redirected to the `/Movies` URL, where you can see the newly created movie in the listing.

.. image:: adding-model/_static/h.png
Expand All @@ -161,11 +188,30 @@ Examining the Generated Code

Open the *Controllers/MoviesController.cs* file and examine the generated ``Index`` method. A portion of the movie controller with the ``Index`` method is shown below:

.. literalinclude:: start-mvc/sample2/src/MvcMovie/Controllers/MoviesController.cs
:language: c#
:start-after: // The Movies Controller
:end-before: // GET: Movies/Details/5
:dedent: 4
.. code-block:: c#
public class MoviesController : Controller
{
private readonly ApplicationDbContext _context;
public MoviesController(ApplicationDbContext context)
{
_context = context;
}
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
.. can't use this because we commenent out the initial index method and update it later
.. comment literalinclude:: start-mvc/sample2/src/MvcMovie/Controllers/MoviesController.cs
:language: c#
:start-after: // The Movies Controller
:end-before: // GET: Movies/Details/5
:dedent: 4
The constructor uses :doc:`Dependency Injection </fundamentals/dependency-injection>` to inject the database context into the controller. The database context is used in each of the `CRUD <https://en.wikipedia.org/wiki/Create,_read,_update_and_delete>`__ methods in the controller.
Expand Down Expand Up @@ -223,7 +269,7 @@ Examine the *Index.cshtml* view and the ``Index`` method in the Movies controlle
.. literalinclude:: start-mvc/sample2/src/MvcMovie/Controllers/MoviesController.cs
:language: c#
:start-after: // GET: Movies
:end-before: // GET: Movies/Details/5
:end-before: // End of first Index
:dedent: 8
When you created the movies controller, Visual Studio automatically included the following ``@model`` statement at the top of the *Index.cshtml* file:
Expand Down Expand Up @@ -252,4 +298,4 @@ Additional resources
-----------------------
- :doc:`/mvc/views/tag-helpers/index`
- :doc:`/fundamentals/localization`
- :doc:`/fundamentals/localization`
9 changes: 5 additions & 4 deletions aspnet/tutorials/first-mvc-app/controller-methods-views.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ Controller methods and views

By `Rick Anderson`_

We have a good start to the movie app, but the presentation is not ideal. We don't want to see the time on the release date and **ReleaseDate** should be two words.
We have a good start to the movie app, but the presentation is not ideal. We don't want to see the time (12:00:00 AM in the image below) and **ReleaseDate** should be two words.

.. image:: working-with-sql/_static/m55.png

Open the *Models/Movie.cs* file and add the highlighted lines shown below:

.. literalinclude:: start-mvc/sample2/src/MvcMovie/Models/MovieDate.cs
:language: c#
:lines: 8-19
:dedent: 4
:lines: 8-18
:emphasize-lines: 6-7
:dedent: 4

- Right click on a red squiggly line **> Quick Actions**.

Expand Down Expand Up @@ -77,6 +77,8 @@ Open the ``Movies`` controller and examine the two ``Edit`` action methods:
:end-before: // POST: Movies/Edit/5
:dedent: 8

.. This method will be updated after we add rating (add it to the bind)
.. literalinclude:: start-mvc/sample2/src/MvcMovie/Controllers/MoviesController.cs
:language: c#
:start-after: // Edit Post
Expand Down Expand Up @@ -141,7 +143,6 @@ The following listing shows the ``[HttpPost]`` version of the ``Edit`` action me
:start-after: // Edit Post
:end-before: // End of Edit Post
:dedent: 8
:linenos:
:emphasize-lines: 1,2,10,14,15,28

The ``[ValidateAntiForgeryToken]`` attribute validates the hidden `XSRF <:doc:/security/anti-request-forgery>`__ token generated by the anti-forgery token generator in the
Expand Down
44 changes: 27 additions & 17 deletions aspnet/tutorials/first-mvc-app/details.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,42 @@ By `Rick Anderson`_
Open the Movie controller and examine the ``Details`` method:

.. literalinclude:: start-mvc/sample2/src/MvcMovie/Controllers/MoviesController.cs
:language: c#
:lines: 29-44
:dedent: 8
:language: c#
:start-after: // GET: Movies/Details/5
:end-before: // GET: Movies/Create
:dedent: 8

The MVC scaffolding engine that created this action method adds a comment showing a HTTP request that invokes the method. In this case it's a GET request with three URL segments, the ``Movies`` controller, the ``Details`` method and a ``id`` value. Recall these segments are defined in Startup.

.. literalinclude:: start-mvc/sample2/src/MvcMovie/Startup.cs
:language: c#
:lines: 80-86
:dedent: 8
:emphasize-lines: 5
:dedent: 12
:emphasize-lines: 6
:start-after: app.UseIdentity();
:end-before: SeedData.Initialize(app.ApplicationServices);

Code First makes it easy to search for data using the ``SingleOrDefaultAsync`` method. An important security feature built into the method is that the code verifies that the search method has found a movie before the code tries to do anything with it. For example, a hacker could introduce errors into the site by changing the URL created by the links from *http://localhost:xxxx/Movies/Details/1* to something like *http://localhost:xxxx/Movies/Details/12345* (or some other value that doesn't represent an actual movie). If you did not check for a null movie, the app would throw an exception.

Examine the Delete and DeleteConfirmed methods.
Examine the ``Delete`` and ``DeleteConfirmed`` methods.

.. literalinclude:: start-mvc/sample2/src/MvcMovie/Controllers/MoviesController.cs
:language: c#
:lines: 119-145
:dedent: 8
:language: c#
:start-after: // GET: Movies/Delete/5
:end-before: private bool MovieExists(int id)
:dedent: 8

Note that the ``HTTP GET Delete`` method doesn't delete the specified movie, it returns a view of the movie where you can submit (HttpPost) the deletion. Performing a delete operation in response to a GET request (or for that matter, performing an edit operation, create operation, or any other operation that changes data) opens up a security hole.

The ``[HttpPost]`` method that deletes the data is named ``DeleteConfirmed`` to give the HTTP POST method a unique signature or name. The two method signatures are shown below:

.. literalinclude:: start-mvc/sample2/src/MvcMovie/Controllers/MoviesController.cs
:language: c#
:lines: 119-120,135-136,139
:dedent: 8
.. code-block:: c#
// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
// POST: Movies/Delete/
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
The common language runtime (CLR) requires overloaded methods to have a unique parameter signature (same method name but different list of parameters). However, here you need two ``Delete`` methods -- one for GET and one for POST -- that both have the same parameter signature. (They both need to accept a single integer as a parameter.)

Expand All @@ -44,7 +51,10 @@ There are two approaches to this problem, one is to give the methods different n
Another common work around for methods that have identical names and signatures is to artificially change the signature of the POST method to include an extra (unused) parameter. That's what we did in a previous post when we added the ``notUsed`` parameter. You could do the same thing here for the ``[HttpPost] Delete`` method:

.. literalinclude:: start-mvc/sample2/src/MvcMovie/Controllers/MoviesController.cs
:language: c#
:dedent: 8
:language: c#
:start-after: // POST: Movies/Delete/6
:end-before: // End of DeleteConfirmed
:dedent: 8


.. ToDo - Next steps, but it really needs to start with Tom's EF/MVC Core
5 changes: 4 additions & 1 deletion aspnet/tutorials/first-mvc-app/new-field.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ Update the ``SeedData`` class so that it provides a value for the new column. A

.. literalinclude:: start-mvc/sample2/src/MvcMovie/Models/SeedDataRating.cs
:language: c#
:lines: 25-32
:start-after: context.Movie.AddRange(
:end-before: // Add another movie.
:dedent: 16
:emphasize-lines: 6

.. warning:: You must stop IIS Express before you run the ``dotnet ef`` commands. See :ref:`stop-IIS-Express-reference-label`

Build the solution then open a command prompt. Enter the following commands:

.. code-block:: console
Expand Down

0 comments on commit affe6e9

Please sign in to comment.