My team has started working on a new web application, and we’ve been asked to use ASP.NET for the backend. We chose to use React for the frontend because we’ve had significant success with React at Atomic, and we wanted to leverage some existing UI components that were built in React.
We try to avoid using IDEs when we can, so for this guide, I’ll be using the command line only.
Creating the App
We’ll start by using the dotnet CLI to generate an ASP.NET + React template. First, install the CLI:
$ brew cask install dotnet-sdk
If you need a specific SDK, you can use this package: dotnet-sdk versions HomeBrew Tap.
To create a template app, run the following command, subbing
sample-project for your project name:
$ dotnet new react -n sample-project
cd into your new project, and let’s poke around!
A Brief Tour
In the newly created
sample-project directory, you’ll see a few key folders:
- ClientApp: Contains the React app. It’s based on Create React App, which has some excellent docs here.
- Controllers: Defines your API endpoints. You can see an example of one in
- Pages: Misleading; contains a default error page for your backend. The “real” frontend lives in ClientApp.
For purposes of this guide, we’ll leave the sample code mostly as-is.
Setup… Sort Of
This template provides a basic web API and frontend out of the box, so to fire things up, you should be able to run:
$ dotnet run
Sigh. As of the time of writing, if I try to run the project immediately, I get a slew of errors. The first one is a warning that:
Browserslist: caniuse-lite is outdated. Please run next command `npm update`
Okay, easy enough. If you see commands that involve
npm, that’s a sign you need to be working in the frontend, so pop into
ClientApp and run that command:
$ cd ClientApp $ npm update $ cd ..
Okay, one problem down. Let’s try running again:
You might have success! But…
I did not. Sigh. I get the following message:
There might be a problem with the project dependency tree. [...]
Fortunately, this message also includes instructions on a fix:
To fix the dependency tree, try following the steps below in the exact order: [...]
But following these steps didn’t get me anywhere.
A bit of digging around the internet regarding this template yields…
almost nothing a few closed Github issues that mostly say “works for me.” So I’m not positive exactly why this issue happens.
But you can sidestep the problem by setting the package version in
ClientApp/package.json to the version listed in the error message. For example:
The react-scripts package provided by Create React App requires a dependency: "babel-eslint": "10.0.3"
For this, I opened
ClientApp/package.json and updated the line:
Then, I blew away my
$ rm -rf ClientApp/node_modules
And I tried running the app again. I repeated this process for a second package, and finally:
$ dotnet run
No failures! Navigate to https://localhost:5001, and check out your new app!
Running the app locally is great and all, but it’s not what you came here for. To set up the app to run in Docker, add a Dockerfile at the root of the repo.
You’ll need to update instances of
sample-app to your app’s name. I’ve included comments that explain each step:
# Pull down an image from Docker Hub that includes the .NET core SDK: # https://hub.docker.com/_/microsoft-dotnet-core-sdk # This is so we have all the tools necessary to compile the app. FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build # Fetch and install Node 10. Make sure to include the --yes parameter # to automatically accept prompts during install, or it'll fail. RUN curl --silent --location https://deb.nodesource.com/setup_10.x | bash - RUN apt-get install --yes nodejs # Copy the source from your machine onto the container. WORKDIR /src COPY . . # Install dependencies. # https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-restore?tabs=netcore2x RUN dotnet restore "./sample-app.csproj" # Compile, then pack the compiled app and dependencies into a deployable unit. # https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish?tabs=netcore21 RUN dotnet publish "sample-app.csproj" -c Release -o /app/publish # Pull down an image from Docker Hub that includes only the ASP.NET core runtime: # https://hub.docker.com/_/microsoft-dotnet-core-aspnet/ # We don't need the SDK anymore, so this will produce a lighter-weight image # that can still run the app. FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim # Expose port 80 to your local machine so you can access the app. EXPOSE 80 # Copy the published app to this new runtime-only container. COPY --from=build /app/publish . # To run the app, run `dotnet sample-app.dll`, which we just copied over. ENTRYPOINT ["dotnet", "sample-app.dll"]
To build the image, run:
$ docker build -t sample-app .
And finally, to run your new Dockerized app:
$ docker run -p 80:80 sample-app
Now, you should be able to visit http://localhost:80 and see your app!
Check the “fetch data” page to make sure your frontend and backend are talking to each other.
In the future, I’d like to build out a solution that allows us to do all of our development in Docker. But for now, this relatively simple solution gets the app up and running for purposes of containerized deployment and system testing in CI.