.NET is the venerable framework that indie and enterprise developers alike have come to love. The ability to choose a variety of languages as well as deploy to a variety of platforms ranging from mobile to servers makes .NET a great choice for all kinds of applications. While .NET does a lot, it doesn’t do everything. For instance, one cannot write client side code to run in a browser in .NET (unless you use Silverlight…) nor is there currently a language supported by .NET that enables developers to write smart contracts.
The language of choice for smart contracts though is Solidity. Solidity is a purpose-built language that assumes many things about the environment it is running it, which pretty much marries it to blockchain technologies. It’s these baked in assumptions that conversely preclude other languages though.
Smart-contracts by themselves though are only half the story. For apps to be complete, smart contracts need something to call them by way of RPC’s. This is where Web3 clients come in. A Web3 client is simply the client side interface that enables client apps to interface with smart contracts running on Ethereum, so as long as one exists for a given language, then it can interface with Ethereum.
For .NET, really the only game in town for Ethereum is a project called Nethereum. (Nethereum is a portmanteau of .NET and Ethereum). This library attempts to replicate the same functionality provided by Web3.js available for JavaScript apps like those that run in a browser and with NodeJS
In this tutorial, we’ll deploy a smart contract to Ganache and then create a simple .NET app using .NET core to interface with the smart contract.
npm install -g truffle
truffle init
in the folder.
truffle init
contract
, test
, and migration
. In the contract folder, create a new file called Vote.sol
in the contracts
folder.Vote.sol
and save the file. This contract simply tracks the vote count for 2 candidates. The contract uses the message sender (that is, an account address) as the voter. It only allows 1 vote per account.
pragma solidity ^0.4.16;
contract Vote {
uint public candidate1;
uint public candidate2;
mapping (address => bool) public voted;
function castVote(uint candidate) public {
require(!voted[msg.sender] && (candidate == 1 || candidate == 2));
if(candidate == 1){
candidate1++;
}else{
candidate2++;
}
voted[msg.sender] = true;
}
}
migrations
folder called 2_vote.js
.2_vote.js
file and save it.
var vote = artifacts.require("Vote");
module.exports = function(deployer) {
// deployment steps
deployer.deploy(vote);
};
truffle.js
in the root of the folder you created and paste in the following code, then save the file. This configures Truffle to use Ganache.
module.exports = {
networks: {
ganache: {
host: "127.0.0.1",
port: 7545,
network_id: "*" // Match any network id
}
}
};
ganache
network is defined in the truffle.js
file.
truffle deploy --reset --network ganache
Vote: 0xe4e47451aad6c89a6d9e4ad104a7b77ffe1d3b36
dotnet
command to create a new console app.
dotnet create new console
dotnet add package Nethereum.Web3
dotnet add package Nethereum.Contracts
Program.cs
file. Paste over the default code with the following code. This will make the console prompt for an account address and for a users vote. Save the file.
using System;
using System.Numerics;
using System.Threading.Tasks;
using Nethereum.Contracts;
using Nethereum.Hex.HexTypes;
using Nethereum.Web3;
namespace console
{
class Program
{
static void Main(string[] args)
{
//The URL endpoint for the blockchain network.
string url = "HTTP://localhost:7545";
//The contract address.
string address = "0x345cA3e014Aaf5dcA488057592ee47305D9B3e10";
//The ABI for the contract.
string ABI = @"[{'constant':true,'inputs':[],'name':'candidate1','outputs':[{'name':'','type':'uint256'}],'payable':false,'stateMutability':'view','type':'function'},{'constant':false,'inputs':[{'name':'candidate','type':'uint256'}],'name':'castVote','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function'},{'constant':true,'inputs':[],'name':'candidate2','outputs':[{'name':'','type':'uint256'}],'payable':false,'stateMutability':'view','type':'function'},{'constant':true,'inputs':[{'name':'','type':'address'}],'name':'voted','outputs':[{'name':'','type':'bool'}],'payable':false,'stateMutability':'view','type':'function'}]";
//Creates the connecto to the network and gets an instance of the contract.
Web3 web3 = new Web3(url);
Contract voteContract = web3.Eth.GetContract(ABI, address);
//Reads the vote count for Candidate 1 and Candidate 2
Task<BigInteger> candidate1Function = voteContract.GetFunction("candidate1").CallAsync<BigInteger>();
candidate1Function.Wait();
int candidate1 = (int)candidate1Function.Result;
Task<BigInteger> candidate2Function = voteContract.GetFunction("candidate2").CallAsync<BigInteger>();
candidate2Function.Wait();
int candidate2 = (int)candidate2Function.Result;
Console.WriteLine("Candidate 1 votes: {0}", candidate1);
Console.WriteLine("Candidate 2 votes: {0}", candidate2);
//Prompts for the account address.
Console.Write("Enter the address of your account: ");
string accountAddress = Console.ReadLine();
//Prompts for the users vote.
int vote = 0;
Console.Write("Press 1 to vote for candidate 1, Press 2 to vote for candidate 2: ");
Int32.TryParse(Convert.ToChar(Console.Read()).ToString(), out vote);
Console.WriteLine("You pressed {0}", vote);
//Executes the vote on the contract.
try{
HexBigInteger gas = new HexBigInteger(new BigInteger(400000));
HexBigInteger value = new HexBigInteger(new BigInteger(0));
Task<string> castVoteFunction = voteContract.GetFunction("castVote").SendTransactionAsync(accountAddress, gas, value, vote);
castVoteFunction.Wait();
Console.WriteLine("Vote Cast!");
}catch(Exception e){
Console.WriteLine("Error: {0}", e.Message);
}
}
}
}
Program.cs
, paste over the value for address with the address for your deploy contact, then save the file.
//The contract address.
string address = "Your address goes here";
dotnet build
dotnet run
Candidate 1 votes: 0
Candidate 2 votes: 0
Enter the address of your account: 0x627306090abaB3A6e1400e9345bC60c78a8BEf57
Press 1 to vote for candidate 1, Press 2 to vote for candidate 2: 1
You pressed 1
Vote Cast!
Candidate 1 votes: 1
Candidate 2 votes: 0
Enter the address of your account: 0xf17f52151EbEF6C7334FAD080c5704D77216b732
Press 1 to vote for candidate 1, Press 2 to vote for candidate 2: 2
You pressed 2
Vote Cast!
With Nethereum, it’s easy to wire up a Smart Contract to any .NET app. Because Nethereum is .NET, it can be used in .NET Core apps, .NET Standard, Xamarin, and all sorts of Windows apps. With Nethereum, the power of Ethereum and .NET is now at your disposal!
Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…
Cloud management is difficult to do manually, especially if you work with multiple cloud…
Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…
https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…
FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…
Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…