MIT License
Service Technical Enhancement Proposals
This repository is licensed under the MIT License. See the LICENSE file for more information.
To use the Codespace environment for this project, follow these steps:
Open Codespace:
Wait for Setup:
Start Coding:
Run and Debug:
CI/CD Integration:
You’ll need an ASP.NET Core backend with SignalR that communicates with CosmosDB.
dotnet new webapi -n SignalRCosmosDemo
cd SignalRCosmosDemo
dotnet add package Microsoft.Azure.Cosmos
dotnet add package Microsoft.AspNetCore.SignalR
In your Hubs
folder, create a RecordHub.cs
file:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
public class RecordHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
Create a CosmosService.cs
that will handle getting/setting records in CosmosDB.
using Microsoft.Azure.Cosmos;
using System.Threading.Tasks;
public class CosmosService
{
private readonly Container _container;
public CosmosService(CosmosClient cosmosClient, string databaseName, string containerName)
{
_container = cosmosClient.GetContainer(databaseName, containerName);
}
public async Task<T> GetRecordAsync<T>(string id, string partitionKey)
{
try
{
ItemResponse<T> response = await _container.ReadItemAsync<T>(id, new PartitionKey(partitionKey));
return response.Resource;
}
catch (CosmosException)
{
return default;
}
}
public async Task SetRecordAsync<T>(T record, string id, string partitionKey)
{
await _container.UpsertItemAsync(record, new PartitionKey(partitionKey));
}
}
Startup.cs
Configure services and SignalR:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// CosmosDB configuration
services.AddSingleton<CosmosClient>(sp =>
new CosmosClient(Configuration["CosmosDB:ConnectionString"]));
services.AddSingleton<CosmosService>(sp =>
new CosmosService(
sp.GetRequiredService<CosmosClient>(),
Configuration["CosmosDB:DatabaseName"],
Configuration["CosmosDB:ContainerName"]));
// Add SignalR
services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<RecordHub>("/recordHub");
});
}
Create a RecordController.cs
file to handle CosmosDB interactions.
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
[ApiController]
[Route("api/[controller]")]
public class RecordController : ControllerBase
{
private readonly CosmosService _cosmosService;
private readonly IHubContext<RecordHub> _hubContext;
public RecordController(CosmosService cosmosService, IHubContext<RecordHub> hubContext)
{
_cosmosService = cosmosService;
_hubContext = hubContext;
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(string id, [FromQuery] string partitionKey)
{
var record = await _cosmosService.GetRecordAsync<dynamic>(id, partitionKey);
if (record == null) return NotFound();
return Ok(record);
}
[HttpPost]
public async Task<IActionResult> Set([FromBody] dynamic record, [FromQuery] string id, [FromQuery] string partitionKey)
{
await _cosmosService.SetRecordAsync(record, id, partitionKey);
await _hubContext.Clients.All.SendAsync("ReceiveMessage", "server", $"Record {id} updated");
return Ok();
}
}
appsettings.json
for CosmosDB{
"CosmosDB": {
"ConnectionString": "<Your CosmosDB Connection String>",
"DatabaseName": "YourDatabase",
"ContainerName": "YourContainer"
}
}
npx create-react-app signalr-cosmos-frontend
cd signalr-cosmos-frontend
npm install @microsoft/signalr axios
.env
fileCreate a .env
file in the root of your React project and add the following environment variables:
REACT_APP_API_BASE_URL=http://localhost:5000
REACT_APP_SIGNALR_HUB_URL=${REACT_APP_API_BASE_URL}/recordHub
App.js
import React, { useEffect, useState } from 'react';
import * as signalR from '@microsoft/signalr';
import axios from 'axios';
function App() {
const [messages, setMessages] = useState([]);
const [record, setRecord] = useState(null);
const [newRecord, setNewRecord] = useState('');
const API_BASE_URL = process.env.REACT_APP_API_BASE_URL || 'http://localhost:5000';
const SIGNALR_HUB_URL = process.env.REACT_APP_SIGNALR_HUB_URL || `${API_BASE_URL}/recordHub`;
useEffect(() => {
// Create SignalR connection
const connection = new signalR.HubConnectionBuilder()
.withUrl(SIGNALR_HUB_URL)
.withAutomaticReconnect()
.build();
connection.start()
.then(() => console.log('Connected to SignalR'))
.catch(err => console.log('Error connecting to SignalR: ', err));
// Receive messages from SignalR hub
connection.on('ReceiveMessage', (user, message) => {
setMessages(prevMessages => [...prevMessages, `${user}: ${message}`]);
});
return () => {
connection.stop();
};
}, [SIGNALR_HUB_URL]);
const getRecord = async () => {
const response = await axios.get(`${API_BASE_URL}/api/record/1`, {
params: { partitionKey: 'default' }
});
setRecord(response.data);
};
const setNewRecordToDb = async () => {
await axios.post(`${API_BASE_URL}/api/record`, { data: newRecord }, {
params: { id: '1', partitionKey: 'default' }
});
setNewRecord('');
};
return (
<div className="App">
<h1>SignalR and CosmosDB Demo</h1>
<div>
<h2>Record</h2>
<button onClick={getRecord}>Get Record</button>
<pre>{JSON.stringify(record, null, 2)}</pre>
</div>
<div>
<h2>Update Record</h2>
<input value={newRecord} onChange={e => setNewRecord(e.target.value)} />
<button onClick={setNewRecordToDb}>Update</button>
</div>
<div>
<h2>Messages</h2>
{messages.map((msg, idx) => <p key={idx}>{msg}</p>)}
</div>
</div>
);
}
export default App;
Backend: Run the ASP.NET Core SignalR server and API:
dotnet run
Frontend: Start the React frontend:
npm start
Fix Issues: Address any issues by running:
npm audit fix --force
RecordHub
) when the page loads./api/record
).This POC demonstrates the basic structure of integrating SignalR for real-time communication, with CosmosDB for storage operations. Let me know if you'd like further details or customization for your scenario!
There are no prerequisites required to run this code or use this repository.
To set up the Codespace environment, ensure you have the following tools installed:
This repository does not hold installable content.
To set up the Codespace environment, follow these steps:
Clone the Repository:
git clone https://github.com/dciborow/GitOpsDevHub.git
cd GitOpsDevHub
Open in Codespace:
Wait for Setup:
Start Coding:
At this time, the repository does not use continuous integration or produce a website, artifact, or anything deployed.
The Codespace environment is integrated with the existing CI/CD pipelines. You can run tests and deploy directly from the Codespace environment.
This repository prefers outside contributors start forks rather than branches. For pull requests more complicated than typos, it is often best to submit an issue first. If you are a new potential collaborator who finds reaching out or contributing to another project awkward, you may find it useful to read these tips & tricks on InnerSource Communication.
The creators of this repository DO NOT EXPECT REUSE. If you do use it, please let us know via an email or leave a note in an issue, so we can best understand the value of this repository.