.NET core + ASP.NET core integration
How to use Vue with .NET core + ASP.NET - free starter
This guide will provide you with a free template for a .NET core + ASP.NET application, with MongoDB database and Vue + Bootstrap 5 front-end.
Prerequisites
Before starting the project make sure to install the following utilities:
- Node LTS (14.x.x or higher recommended)
- .NET 6.0 SDK
- Code editor. We recommend VSCode
Creating a new ASP.NET application
In this tutorial we will create a fresh ASP.NET application with MongoDB database. Navigate to your project directory, i.e. mdb-vue-aspnet-app
and follow the steps below.
Note: The latest versions of ASP.NET don't have a Startup.cs
class. In this tutorial we are using version 6 where dependencies and middleware are registered inside the Program.cs
class.
Step 1
Creating MongoDB database.
In order to create a new database you need to run the following command:
mdb database init -db mongodb
- Create a new user
- Provide username, password, database name and description.
Note: the password must contain at least one uppercase letter, one lowercase letter, one number, one special symbol and have minimum length of 8.
Important Do not close your terminal window until you save your credentials somewhere. This is the only time we will show you your database password. If you won't save it you'll loose it.
Step 2
Create a new project with a webapi
template and call it MDBASPNETMongoDB (or whatever you like) ...
dotnet new webapi -o MDBASPNETMongoDB
... and add MongoDB.Driver
package. Also let's remove files that are not necessary for our project: WeatherForecast.cs
and Controllers/WeatherForecastController.cs
.
cd MDBASPNETMongoDB
dotnet add package MongoDB.Driver
Step 3
First thing we are going to do is to create a Models
directory. Inside that folder create a file named MongoDBSettings.cs
where we will define ConnectionURI, DatabaseName and CollectionName
.
namespace MDBASPNETMongoDB.Models;
public class MongoDBSettings
{
public string ConnectionURI { get; set; } = null!;
public string DatabaseName { get; set; } = null!;
public string CollectionName { get; set; } = null!;
}
Step 4
Go to appsettings.json
and create a new MongoDB
object with 3 fields: ConnectionURI, DatabaseName and CollectionName
. In first two you have to provide the info from the database you created earlier. In the last one let's put tasks
as a value.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"MongoDB": {
"ConnectionURI": "Your DB_CONNECTION_STRING",
"DatabaseName": "Your DatabaseName",
"CollectionName": "tasks"
}
}
Step 5
Create a new model called TaskItem.cs
inside a Models
directory. It's time to define a TaskItem
.
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace MDBASPNETMongoDB.Models;
public class TaskItem
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string? id { get; set; }
public string name { get; set; } = null!;
public string desc { get; set; } = null!;
}
Step 6
Create a new directory called Services
and put a new file inside named MongoDBService.cs
. It's going to store a service that will be responsible for connecting the app with MongoDB.
Import necessary dependency. Now we can define a MongoDBService
class and create a methods that will be responsible for handling request sent to our API.
using MDBASPNETMongoDB.Models;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using MongoDB.Bson;
namespace MDBASPNETMongoDB.Services;
public class MongoDBService
{
private readonly IMongoCollection<TaskItem> _taskCollection;
public MongoDBService(IOptions<MongoDBSettings> mongoDBSettings)
{
MongoClient client = new MongoClient(mongoDBSettings.Value.ConnectionURI);
IMongoDatabase database = client.GetDatabase(mongoDBSettings.Value.DatabaseName);
_taskCollection = database.GetCollection<TaskItem>(mongoDBSettings.Value.CollectionName);
}
public async Task<List<TaskItem>> GetAsync()
{
return await _taskCollection.Find(new BsonDocument()).ToListAsync();
}
public async Task CreateAsync(TaskItem task)
{
await _taskCollection.InsertOneAsync(task);
return;
}
public async Task UpdateAsync(string id, string name, string desc)
{
FilterDefinition<TaskItem> filter = Builders<TaskItem>.Filter.Eq("id", id);
UpdateDefinition<TaskItem> update = Builders<TaskItem>.Update.Set("name", name).Set("desc", desc);
await _taskCollection.FindOneAndUpdateAsync(filter, update);
return;
}
public async Task DeleteAsync(string id)
{
FilterDefinition<TaskItem> filter = Builders<TaskItem>.Filter.Eq("id", id);
await _taskCollection.DeleteOneAsync(filter);
return;
}
}
Step 7
Let's go to Program.cs
file and import a few MongoDB dependencies on top of that file. We also have to to bind our settings and MongoDBService after init of a builder
variable. Lastly, we are going to add some code to remove CORS problems that would appear later.
using MDBASPNETMongoDB.Models;
using MDBASPNETMongoDB.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(); // for CORS to work properly
builder.Services.Configure<MongoDBSettings>(builder.Configuration.GetSection("MongoDB"));
builder.Services.AddSingleton<MongoDBService>();
...
var app = builder.Build();
app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()); // for CORS to work properly
...
app.Run();
Step 8
Create a new controller inside a Controllers
directory. Our default API route will be /tasks
. If you look at the code below, we are defining get, post, put and delete
endpoints that will be necessary for a basic front-end app.
using System;
using Microsoft.AspNetCore.Mvc;
using MDBASPNETMongoDB.Services;
using MDBASPNETMongoDB.Models;
namespace MDBASPNETMongoDB.Controllers;
[Controller]
[Route("tasks/")]
public class TaskController : Controller
{
private readonly MongoDBService _mongoDBService;
public TaskController(MongoDBService mongoDBService)
{
_mongoDBService = mongoDBService;
}
[HttpGet]
public async Task<List<TaskItem>> Get()
{
return await _mongoDBService.GetAsync();
}
[HttpPost]
public async Task<IActionResult> Post([FromBody] TaskItem task)
{
await _mongoDBService.CreateAsync(task);
return CreatedAtAction(nameof(Get), new { id = task.id }, task);
}
[HttpPut("{id}")]
public async Task<IActionResult> AddToTask(string id, [FromBody] TaskItem response, [FromBody] string desc)
{
await _mongoDBService.UpdateAsync(id, response.name, response.desc);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(string id)
{
await _mongoDBService.DeleteAsync(id);
return NoContent();
}
}
Step 9
Run your backend app and go to https://localhost:YOUR_BACKEND_PORT/swagger/index.html
and test your endpoints with Try it out
button. If everything works fine we can start creating a new vue project.
dotnet run
Creating MDB Vue application
If our backend is working correctly we should start creating a new Vite application. If you have encountered any problems, you should go back and try each step again.
Note: Don't forget to go back to your root folder before next step. Folders MDBASPNETMongoDB
and mdb5-free-vue
should be in the same directory.
Step 1
Create a new vite project with our MDB starter. Run the command below and select MDB5 Free Vue
starter.
mdb init
Your folder structure should look like this
Step 2
Let's make some changes to the created vue app. First we need to install axios
inside our mdb5-free-vue
directory.
npm install axios
Remove style.css
file (don't forget to delete it from main.ts
file) and remove HelloWorld
file from components directory.
Step 3
Let's create a .env
file inside a mdb5-free-vue directory. We have to add VITE_
before the name of your variable, because it's the only way to expose them to Vite-processed code. Don't forget to change YOUR_BACKEND_PORT
to the port your backend is running right now.
VITE_API = "LINK_TO_YOUR_BACKEND_APP"
Step 4
Add new content to Home.vue
file inside the views
directory.
Since our starter database contains some sample models and routes, let's use them. We will create an application that will show a list of tasks. We also intend to create a functonality for adding new tasks, changing their content and removing them.
We have already prepared the code for you, so go ahead and copy and paste it into App.vue
.
Ok, so what's actually going on there. We use MDB components, MDBBtn, MDBModal, MDBListGroup, MDBInputs
and few other. The modal will be responsible to show inputs that will allow you to add, edit and send tasks to the database. The Manage tasks
button, gives possibilty to modify or remove tasks. At the end, the list group will display our data.
<template>
<MDBContainer class="mt-5">
<MDBRow class="pt-5">
<MDBCol class="text-center">
<MDBBtn color="primary" @click="taskModal = true">Add task</MDBBtn>
</MDBCol>
</MDBRow>
<MDBRow class="mt-3 p-5" style="min-height: 40vh">
<MDBCol class="d-flex justify-content-center align-items-center">
<div v-if="taskList.length === 0">
Nothing to display. Add a few tasks.
</div>
<MDBListGroup v-else class="list-group-light" style="min-width: 22rem">
<MDBListGroupItem
class="d-flex justify-content-between align-items-center gap-5"
v-for="task in taskList"
:key="task.id"
>
<div>
<div class="fw-bold">
{{ task.name }}
</div>
<div class="text-muted">{{ task.desc }}</div>
</div>
<div>
<MDBIcon
class="text-primary me-3"
title="edit"
icon="pen"
style="cursor: pointer"
@click="() => editModal(task)"
/>
<MDBIcon
class="text-danger"
title="delete"
icon="trash"
style="cursor: pointer"
@click="() => deleteTask(task.id)"
/>
</div>
</MDBListGroupItem>
</MDBListGroup>
</MDBCol>
</MDBRow>
</MDBContainer>
<MDBModal
id="addNewTaskModal"
tabindex="-1"
labelledby="addNewTaskModalLabel"
v-model="taskModal"
>
<MDBModalHeader>
<MDBModalTitle id="exampleModalLabel">{{
isEdited.edited ? "Edit task" : "Add task"
}}</MDBModalTitle>
</MDBModalHeader>
<MDBModalBody>
<form>
<div class="my-4">
<MDBInput
label="Name"
type="text"
v-model="newTaskName"
counter
:maxlength="60"
/>
</div>
<div class="my-4">
<MDBInput
label="Description"
type="text"
v-model="newTaskDesc"
counter
:maxlength="255"
/>
</div>
</form>
</MDBModalBody>
<MDBModalFooter>
<MDBBtn
color="secondary"
@click="
{
resetInputs();
taskModal = false;
}
"
>Close</MDBBtn
>
<MDBBtn
color="primary"
@click="handleSaveChanges"
:disabled="!canSendData"
>{{ isEdited.edited ? "Save changes" : "Add task" }}</MDBBtn
>
</MDBModalFooter>
</MDBModal>
</template>
<script setup lang="ts">
import { ref, onMounted, computed } from "vue";
import {
MDBContainer,
MDBRow,
MDBCol,
MDBListGroup,
MDBListGroupItem,
MDBBtn,
MDBModal,
MDBModalTitle,
MDBModalHeader,
MDBModalBody,
MDBModalFooter,
MDBInput,
MDBIcon,
} from "mdb-vue-ui-kit";
import axios from "axios";
interface SingleTask {
id: number;
name: string;
desc: string;
}
const taskList = ref<SingleTask[]>([]);
const taskModal = ref(false);
const newTaskName = ref("");
const newTaskDesc = ref("");
const isEdited = ref({ edited: false, value: -1 });
const API_URL = ref("");
const canSendData = computed(() => {
if (newTaskName.value.trim() === "" || newTaskDesc.value.trim() === "") {
return false;
}
return true;
});
const resetInputs = () => {
newTaskName.value = "";
newTaskDesc.value = "";
isEdited.value = { edited: false, value: -1 };
};
const handleSaveChanges = async () => {
if (!canSendData.value) {
return;
}
isEdited.value.edited
? updateTask(isEdited.value.value, newTaskName.value, newTaskDesc.value)
: createTask(newTaskName.value, newTaskDesc.value);
resetInputs();
taskModal.value = false;
};
const editModal = (task: SingleTask) => {
newTaskName.value = task.name;
newTaskDesc.value = task.desc;
isEdited.value = { edited: true, value: task.id };
taskModal.value = true;
};
const getTaskList = () => {
axios.get(`${API_URL.value}tasks`).then((res) => (taskList.value = res.data));
};
const createTask = (name: string, desc: string) => {
const data = { name, desc };
axios.post(`${API_URL.value}tasks`, data).then(() => {
getTaskList();
});
};
const deleteTask = (id: number) => {
axios.delete(`${API_URL.value}tasks/${id}`).then(() => {
getTaskList();
});
};
const updateTask = (id: number, name: string, desc: string) => {
const data = { name, desc };
axios.put(`${API_URL.value}tasks/${id}`, data).then(() => {
getTaskList();
});
};
onMounted(() => {
API_URL.value = import.meta.env.VITE_API;
getTaskList();
});
</script>
Step 5
The app should be fully functional and should work correctly with backend
npm start
Optimization
If you want to further optimize your application please visit:
Backend features
ASP.NET core:
This example was created with use of ASP.NET core 6. By creating new endpoints, we can pass or receive data from MDB Vue front-end application.
Frontend features
MDB UI KIT:
To create the project we used our ui kit, with which we can build basic views very quickly.
Views and Layouts:
In this project we used the Home.vue
file, created by the Vite tool in which we placed our vue
code. We have successfully integrated the backend with the MDB Vue package and can send basic requests to ASP.NET core application.