Using ASP.NET Core with MS SQL Server and Scaffolding on Linux

This post assumes you have .NET Core SDK and Microsoft SQL Server installed on your machine. I'm using the latest version of .NET Core 1.1 (1.1.0-preview1-005077) and Microsoft SQL Server 2017 (RC1) on Ubuntu 17.04.

Creating a simple MVC app

Let's open the terminal and use the dotnet command with Individual authentication and LocalDB to have a nice boilerplate!

dotnet new mvc --auth Individual --use-local-db true -o BlogPost

Now, we just need to change the connection string inside appsettings.json to something like:

"DefaultConnection": "Server=localhost;Database=your-db-name;Trusted_Connection=False;MultipleActiveResultSets=true;user id=sa;password=your-sophisticated-password"

and Ta-Da! We can use MS SQL Server with ASP.NET Core on Linux! For more information about connection strings, consult SQL Server Connection Strings for ASP.NET Web Applications.

Scaffolding with aspnet-codegenerator

This version of .NET Core creates a .csproj with the required NuGet packages for scaffolding. Just run dotnet aspnet-codegenerator and have fun with it :D

If you can't use the latest preview release, then you may want to add System.Composition, Microsoft.Composition and Microsoft.VisualStudio.Web.CodeGeneration.Design packages to your project using the following commands:

dotnet add package System.Composition

dotnet add package Microsoft.Composition

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design

Finally, Run dotnet restore followed by one of the following commands to see the available options to scaffold your views, controllers and areas :)

dotnet aspnet-codegenerator view -h

dotnet aspnet-codegenerator controller -h

dotnet aspnet-codegenerator area -h

I found myself creating a model (Say Post.cs) then executing the following command to scaffold a controller, views and the data context:

dotnet aspnet-codegenerator controller -name PostsController -m BlogPost.Models.Post -dc BlogPost.Models.PostContext --relativeFolderPath Controllers -scripts --useDefaultLayout

For more information, see SO's How to generate controller using dotnetcore command line, SO's Reference .NET 4.5 dll in .NET Core 1.1 csproj? and Visual Studio Code extension: ASP.NET Core Scaffolding.

A side note: There's a ticket opened on GitHub to track documenting aspnet-codegenerator. Let's hope it'll be published soon! I hope this post was helpful to you :)

Helpful resources and notes for Udacity's web development course

Udacity's web development course is one of my favorite online courses. It teaches some aspects of the front-end and focuses on the back-end. It helped me understand scaling, caching, security and how to create RESTful APIs.

I think the following resources and notes will help you in this course:

  • If you need a refresher on Python or want to learn Python, consider Google’s Python Class (2-days) or/and Official Python Tutorial. Ultimately, you should learn about some of the built-in functions like dir(), help() and type()

  • Download Official Python Documentation to learn Python and search for answers for your Python questions!

  • Read Mozilla's Getting started with the web or/and take Udacity’s Intro to HTML and CSS course in case you want to learn a little bit more about HTML, CSS and JavaScript

  • Note that this course uses Google App Engine Standard Environment and App Engine SDK for Python (Click on "Optionally, you can also download the original App Engine SDK for Python" on their download page to get the SDK)

  • Many applications and tools can run from the terminal (Click Start menu and search for cmd for Windows) but you will need to tell the Operating System where to find these tools by adding their directories to the PATH environment variable (Some installers do this for us). After downloading App Engine SDK zip file, unzip/extract it and:

    • Search for how to add directories to the PATH for Windows! I don't have Windows nowadays and mostly the path will be updated by the installers. The following (3) steps & commands are not helpful for Windows

    • Open the Terminal (for Linux and maybe macOS, Press Ctrl + Alt + T), type each command of the following commands and hit Enter:

      1. Change the current directory to your App Engine SDK directory using cd:

        cd /home/badersur/Downloads/google_appengine
        
      2. Make your files executable (for Ubuntu/Linux and maybe for macOS. Read Ubuntu's File Permissions document for details):

        chmod u+x dev_appserver.py appcfg.py
        
      3. Open ~/.bashrc or ~/.profile or /etc/profile.d/my_env_vars.sh (Read Ubuntu's Environment Variables document for details):

        gedit ~/.bashrc
        
    • Add App Engine SDK directory to the PATH by adding these lines to the chosen file above:

      google_appengine=/home/badersur/Downloads/google_appengine
      
      export PATH=$PATH:$google_appengine
      

      Or create an alias for your files instead of adding the directories to the PATH (I've added these lines to ~/.bashrc):

      alias dev="/home/badersur/Downloads/google_appengine/dev_appserver.py"
      
      alias appcfg="/home/badersur/Downloads/google_appengine/appcfg.py"
      

      You can use any name for the aliases but make sure you don't hide another command by them! (Open the terminal, type the command/alias, press Tab, and if you don't see a suggestion then you can use it safely) Now we can use dev & appcfg instaed of dev_appserver.py & appcfg.py. Ubuntu 16.04 deletes the contents of /tmp -which is used by dev_appserver to store my data locally- on shutdown. This causes losing my data so I use an alias with a dev_appserver's option to solve this issue like this:

      gae_opt="--storage_path=/home/badersur/Downloads/gae_data"
      
      alias dev="/home/badersur/Downloads/google_appengine/dev_appserver.py $gae_opt"
      
    • You should close the terminal after updating ~/.bashrc or ~/.profile, and you should restart your computer or log out after updating /etc/profile.d/my_env_vars.sh

  • Note also that this course does not use any billable components from Google Cloud Platform (App Engine) so there is no need to sign up for a free trial. Just make sure you have a google account, log in to Google Cloud Console, create a new project and note the id (which you can edit to any thing you like) that will be part of your web application url (i.e. your-project-id.appspot.com) and will be used for deployment

  • You should keep your project files in a separate place other than App Engine SDK folder!

  • I suggest completing Lesson 2a - Templates before solving Problem Set 2!

  • Follow App Engine’s tutorial: Creating a Guestbook Application to understand URL handlers, Google's Cloud Datastore, Jinja2 templates, serving static files (like: .css, .js & .png) and deployment - I suggest after lesson 2 and before lesson 4. Open the terminal/cmd and:

    • Type dev_appserver.py --port [PORT_NUMBER] [YOUR_APP_DIR] to test your web application locally (omit --port [PORT_NUMBER] to use the default: 8080, and type dev_appserver.py -h to know about other available options)

    • Type appcfg.py update [YOUR_APP_DIR] -A [YOUR_PROJECT_ID] -V [YOUR_VERSION_ID] to deploy your app (omit -A [YOUR_PROJECT_ID] -V [YOUR_VERSION_ID] if you have set your application's values for application and version in app.yaml). Note: Set debug to False in your webapp2.WSGIApplication(...) before deployment or remove it.

  • This course uses webapp2 web framework which is compatible with Google App Engine’s webapp. Note that:

    • self.response.write() is similar to self.response.out.write() so you can use any of 'em

    • By default, the Content-Type header is text/html; charset=utf-8, including the encoding behavior. If you want to change it use self.response.headers['Content-Type']

  • App Engine encourages us to use NDB Client Library instead of the older DB Client Library (i.e. we should use from google.appengine.ext import ndb instead of from google.appengine.ext import db):

    Note: Developers building new applications are strongly encouraged to use the NDB Client Library, which has several benefits compared to this client library, such as automatic entity caching via the Memcache API. If you are currently using the older DB Client Library, read the DB to NDB Migration Guide

  • App Engine also recommends using Datastore queries over GQL to access the full range of Cloud Datastore's query capabilities

  • So you submitted something to Datastore but it didn't show up immediately? Well, you should set a parent key in each entity to form an entity group and query these entities using this key (Mr. Steve used the parent key in Problem Set 3 and explained it more in the Ancestors video in Wrap-Up Questions and I've answered a question about this)

  • Download an IDE/editor that understands Python! At least it should be able to indent/format your code and provide code snippets. PyCharm Professional Edition has a great support for GAE and other projects, and you can tweak the Community Edition to support GAE. Also, VS Code supports Python & GAE via Don's Python extension

  • You may want to use freegeoip.net/ or ipinfo.io/ APIs to obtain user’s location for lesson 5. But note that App Engine adds several headers to all requests like X-AppEngine-CityLatLong so we can use it instead of these APIs!

  • Download instructor’s HW solutions: HW2, HW3, HW4 & HW5

  • Visit stackoverflow.com/questions/tagged/google-app-engine for questions and answers about App Engine

  • You should include the contents of your app.yaml, wsgi applications ( i.e. app = webapp2.WSGIApplication(...) ) and your project structure in your question if you have an issue with URL handlers

  • In app.yaml, you should set secure subelement of the handlers to always for pages that accept critical values from users (like signup & login pages):

    handlers:
    - url: /signup
      script: signing.app
      secure: always
    
    - url: /login
      script: signing.app
      secure: always
    

Extra

The previous resources are more than enough for the course, but if you need more:

Some of these notes are answers for Frequently Asked Questions (FAQs) but without the questions :P

I hope you've enjoyed reading this post as much as I've enjoyed writing & updating it :)

Hello world!

Hello people and welcome to my new and awesome blog :D

It's been a while since the last time I've posted something on my old WordPress blog. I have no intention to post a lot and my main purpose is to implement as much as I can in this blog and to share my projects with you. I may post about technical stuff (like implemented features or features I'd like to implement or things I've learned) and some aspects of my life, I believe! :)