Blog post image

Using Vuejs with ASP.NET Core MVC

AuthorGenesis Rivera Rios
Date
2/18/2021
Time11 min read

In this blog post I’ll be showing how you can use Vue Js with ASP.NET CORE MVC.

This post is going to be very straightforward since we’re only going to use a newly created asp.net core project with the MVC architecture and create Vue Js instances as we need. We’re also going to see the basics of Vue JS such as conditional statements and data binding.

Starting

To start, let’s create a new project in visual studio. We’re going to go with a Asp.Net Core Web Application.

Asp Net Core new project

In this post I'm using dotnet 5.

Like you probably already know the MVC architecture uses models, views and controllers for separation of concerns. We’re going to be focusing on views and controllers since we don’t have an actual data base and we’re going to be using in memory lists to display information.

Now that we have our simple app let’s import the Vue JS CDN so we can start using it.

Vue JS CDN

Vue JS has really good documentation, in the area where they explain how to install Vue they have the official CDN.

Oficial Vue JS Docs

In the moment of writing this blog post I’m using version 2.6.12 of Vue Js.

Im going to add the CDN link on the file named _Index.cshtml in the Views > Home folder.

I added it under the HTML the Project brings by default.

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    <div id="app">
        <h1 class="display-4">{{message}}</h1>
    </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>

Now if debug our project and we go to the Network Tab of our browser we’ll see the Vue Js script being used.

Network tab

Using Vue Js

Now we can start using Vue Js in our Index.cshtml.

Now we’re going to open up another script tag and let’s write a new Vue instance.

<script>
    let app = new Vue({
        el: '#app',
        data: {
            message: `Vue in the works!`
        }
    })
</script>

Now in our HTML we can use the message in our view instance. As you can see we wrote the message in the HTML using curly brackets around the word. This is because Vue uses template syntax to bind data and the most simple form of binding data is using the curly brackets or mustache syntax.

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    <div id="app">
        <h1 class="display-4">{{message}}</h1>
    </div>
</div>

Now if we debug our project we’ll see our message from Vue being displayed. Vue message

Using data from the server

Now let’s use a ViewModel in which we’ll create a C# record (like a class) and were going to return it to the view Index.cshtml and then use it on Vue.

Let’s create a file in the Models directory and call it IndexViewModel.cs.

Index view model

Now let’s create two records one will represent a User and the other will be the IndexViewModel which we’ll return to the View.

public record User
{
	public string Username { get; set; }
	public string Name { get; set; }
	public string LastName { get; set; }
}
public record IndexViewModel
{
	public User User { get; set; }

	public List<User> FriendList { get; set; }
}

Now let’s create a new user for our ViewModel and return it.

public IActionResult Index()
{
	var model = new IndexViewModel
	{
		User = new User
		{
			LastName = "Rivera",
			Name = "Genesis",
			Username = "genesisrrios"
		}
	};
	return View(model);
}

Before using our ViewModel we have to start by adding this line: @model IndexViewModel;

Now in our view instance let’s use the model to display data. To use the data we’ll reference our model in vue, in this case I created a User object and added three properties which have the values of our Model.

let app = new Vue({
	el: '#app',
	data: {
		user: {
			user_name: '@Model.User.Username',
			last_name: '@Model.User.LastName',
			name: '@Model.User.Name'
		}
	}
})

To use our user object we’ll use dot notation, which means the object name in this case user and a dot and the property name.

<div id="app">
	<h1 class="display-4">User: {{user.name}}</h1>
	<h2 class="display-4">Last name: {{user.last_name}}</h2>
	<h2 class="display-4">Username: {{user.user_name}}</h2>
</div>

Result:

User object vue

Conditional statements and directives

Vue Js has directives that are basically HTML attributes which go inside HTML elements in the DOM and they all start with v- to indicate theyre Vue attributes.

v-if

For example if we wanted to show an element only if a certain condition is true we could use v-if or v-show.

Now if we add to our Vue instance a new list called friends_list and we create new elements in the DOM with a condition like this v-if=”friends_list.length > 0” this will only render if the list is not empty.

Javascript

data: {
	user: {
		user_name: '@Model.User.Username',
		last_name: '@Model.User.LastName',
		name: '@Model.User.Name'
	},
	friends_list: []
}

HTML

<div class="row py-lg-5" v-if="friends_list.length > 0">
	<div class="col-lg-6 col-md-8 mx-auto">
		<p>
		</p>
	</div>
</div>

v-for

Let’s go back to the controller and create a new list of friends inside the View Model.

Now our Index method looks like this.

public IActionResult Index()
{
	var model = new IndexViewModel
	{
		User = new User
		{
			LastName = "Rivera",
			Name = "Genesis",
			Username = "genesisrrios"
		},
		FriendList = new List<User>
		{
			new User
			{
				LastName = "Ford",
				Name = "Henry",
				Username = "henryford121"
			},
			new User
			{
				LastName = "Montgo",
				Name = "Suzzie",
				Username = "mongosus"
			},
			new User
			{
				LastName = "Rivera",
				Name = "Luis",
				Username = "starraiden"
			}
		}
	};
	return View(model);
}

To use our list we’re going to serialize it (Convert to Json) and then deserialize it (Convert to javascript objects). We’re going to use something called mounted in Vue js and it’s basically used to do something after the Vue instance is created but before the user actually see it. If you want to know more click here.

mounted: function () {
}

Using mounted I’m going to use the list in our model and assign it to a variable named friendList which will also serialize it. Then assign it to the reactive property called friends_list which is going to also de serialize the values.

let app = new Vue({
	el: '#app',
	data: {
		user: {
			username: '@Model.User.Username',
			lastName: '@Model.User.LastName',
			name: '@Model.User.Name'
		},
		friends_list: []
	},
	mounted: function () {
		let friendList = '@Html.Raw(Json.Serialize(Model.FriendList))';
		this.friends_list = JSON.parse(friendList);
	}
})

Before referencing reactive data we must use the keyword this followed by a dot in order to correctly reference a property because you might find yourself with an error otherwise.

Now let’s show the data in our HTML, we're going to change our HTML for:

<div class="text-center">
    <div id="app">
        <h1 class="display-4">User: {{user.name}}</h1>
        <h2 class="display-4">Last name: {{user.lastName}}</h2>
        <h2 class="display-4">Username: {{user.username}}</h2>
        <hr />
        <div v-if="friends_list.length > 0">
            <h2 class="display-4">Friends!</h2>
            <ul class="list-group list-group-flush" v-for="friend in friends_list">
                <li class="list-group-item">User: {{friend.name}}, Last Name {{friend.lastName}}, Username: {{friend.username}}</li>
            </ul>
        </div>
    </div>
</div>

As you can see when we access elements using v-for we're iterating over the list created in our instance called friends_list and we created a variable called friend which is used to access the elements in our list that’s why we’re using friend.username etc.

Now if we debug our code we'll see:

Friends list

Reactiveness

You probably noticed everything I did here could’ve been done with razor, the veauty (get it?) of Vue is in the reactiveness and being able to refresh data without refreshing the whole screen so let’s try that.

We’re going to use the Fetch api to do post requests and get requests on the server.

Since we don’t have a data base let’s move the list to the session temporary storage in Asp.net core. This is obviously not the way to do things but since I’m keeping things simple I’ll persist data that way. The important thing here is returning the list and adding ítems to it.

Let’s change our Index to use TempData.

public IActionResult Index()
{
	var friendsList = new List<User>
		{
			new User
			{
				LastName = "Ford",
				Name = "Henry",
				Username = "henryford121"
			},
			new User
			{
				LastName = "Montgo",
				Name = "Suzzie",
				Username = "mongosus"
			},
			new User
			{
				LastName = "Rivera",
				Name = "Luis",
				Username = "starraiden"
			} 
	};
	TempData[TempDataFriendsList] = JsonConvert.SerializeObject(friendsList);
	var model = new IndexViewModel
	{
		User = new User
		{
			LastName = "Rivera",
			Name = "Genesis",
			Username = "genesisrrios"
		},
		FriendList = friendsList
	};
	return View(model);
}

Now let’s add two methods one is going to be a post request to add friends to the list and another one to return the list.

[HttpPost]
public bool InsertNewFriendInMemory([FromBody]User friend)
{
if (friend == default || !TempData.ContainsKey(TempDataFriendsList)) return false;
	var tempData = TempData[TempDataFriendsList];
	var deserializedData = JsonConvert.DeserializeObject<List<User>>((string)tempData);
	deserializedData.Add(friend);
	TempData[TempDataFriendsList] = JsonConvert.SerializeObject(deserializedData);
	return true;
}
public List<User> GetFriendsList()
{
	var tempData = TempData[TempDataFriendsList];
	TempData.Keep();
	var deserializedData = JsonConvert.DeserializeObject<List<User>>((string)tempData);
	return deserializedData;
}

Now we’re going to add some inputs to write the name, last name and username of our friends in order to display it under in the friends list. To do this we’re going to use two way data binding using v-model.

<hr />
<h1 class="display-4">Create new friend</h1>
<div class="input-group mb-3">
	<div class="input-group-prepend">
		<span class="input-group-text" id="basic-addon1"></span>
	</div>
	<input type="text" class="form-control" v-model="new_friend.name" placeholder="Name" aria-label="Name" aria-describedby="basic-addon1">
</div>
<div class="input-group mb-3">
	<div class="input-group-prepend">
		<span class="input-group-text" id="basic-addon1"></span>
	</div>
	<input type="text" class="form-control" v-model="new_friend.lastName" placeholder="Name" aria-label="Name" aria-describedby="basic-addon1">
</div>
<div class="input-group mb-3">
	<div class="input-group-prepend">
		<span class="input-group-text" id="basic-addon1"></span>
	</div>
	<input type="text" class="form-control" v-model="new_friend.userName" placeholder="Name" aria-label="Name" aria-describedby="basic-addon1">
</div>
<button type="button" class="btn btn-dark">Add user</button>
<hr />

In our Vue instance we’re going to create an object alike the user one we created previously called new_friend.

new_friend: {
	username: "",
	lastName: "",
	name: ""
},

This object will contain the values we write in our inputs.

Now we’re going to use fetch api to do a post request to the endpoint we created before and add the values to the friends list. After the post request is done being executed and the promise is resolved we use the value from the method to check if it’s true and invoke the getFriendsList method which has the get request that assigns the new list to the friends list in our Vue instance.

getFriendsList: function () {
	let self = this;
	fetch('@Url.Action("GetFriendsList", "Home")')
		.then(response => response.json())
		.then(data => self.friends_list = data);
},
addFriend: function () {
	let self = this;
	fetch('@Url.Action("InsertNewFriendInMemory", "Home")', {
		method: 'POST',
		headers: {
			'Content-Type': 'application/json',
		},
		body: JSON.stringify(self.new_friend),
	})
	.then(response => response.json())
	.then(data => {
		if (data)
			self.getFriendsList();
	})
}

Let’s add a method to remove friends from the list. First in our HTML lets change the list so it’s clickable and add a removeFriend method which will be invoked when the user click a list item. Using v-on with the click event we can send values from our friend object created in the for loop.

The important part of this code is the list items having the v-on attribute which is used to listen to events in this case click event and when clicked it will trigger the removeFriend method which takes three parameters we get from our friend object created in the for loop. HTML

<div v-if="friends_list.length > 0">
	<h2 class="display-4">Friends!</h2>
	<div class="list-group"  v-for="friend in friends_list">
		<a v-on:click="removeFriend(friend.username, friend.lastName, friend.name)" class="list-group-item list-group-item-action">
			User: {{friend.name}}, Last Name {{friend.lastName}}, Username: {{friend.username}}
		</a>
	</div>
</div>

Javascript

removeFriend: function (username, lastName, name) {
	let self = this;
	let deleteParameters = {
		username: username,
		lastName: lastName,
		name: name
	};
	fetch('@Url.Action("RemoveFriend", "Home")', {
		method: 'DELETE',
		headers: {
			'Content-Type': 'application/json'
		},
		body: JSON.stringify(deleteParameters)
	})
	.then(response => response.json())
	.then(data => {
		if (data)
			self.getFriendsList();
	})
}

C#

[HttpDelete]
public bool RemoveFriend([FromBody] User friend)
{
	if (friend == default || !TempData.ContainsKey(TempDataFriendsList)) return false;
	var tempData = TempData[TempDataFriendsList];
	var deserializedData = JsonConvert.DeserializeObject<List<User>>((string)tempData);
	deserializedData.Remove(friend);
	TempData[TempDataFriendsList] = JsonConvert.SerializeObject(deserializedData);
	return true;
}

You made it to the end!

That’s it for now. These basics cover something’s you need to know to get started with Vue. In the next couple of posts I’ll write about mixins, components and some other interesting stuff Vue Js has.

Category: dotnetvuejs