Appearance
.NET Widget Create
Detailed usage guide for creating new widget projects for .NET platform.
Overview
The xcons dotnet create command creates a ready-to-use hybrid widget project for the .NET platform. A full stack widget project combining ASP.NET Core backend and TypeScript frontend is automatically configured, Visual Studio 2022 integration, IDE configurations and build system setup are done.
Command Syntax
bash
xcons dotnet create [options]
npx @xcons/cli dotnet create [options]Options
| Option | Shorthand | Type | Default | Description |
|---|---|---|---|---|
--name <name> | -n | string | - | .NET project name |
--description <desc> | -d | string | - | Project description |
--no-interaction | - | flag | false | Interactive questions are not asked |
Usage Examples
1. Interactive Mode (Recommended)
Simplest usage - command interactively asks for required information:
bash
xcons dotnet createInteraction:
? .NET Project name: dashboard-api
? .NET Project description: Dashboard API with real-time data
? Do you want to run npm install now? Yes
? Do you want to run dotnet restore now? Yes2. With Name Parameter
Provide project name as parameter:
bash
xcons dotnet create -n dashboard-apiInteraction:
? .NET Project description: Dashboard API with real-time data
? Do you want to run npm install now? Yes
? Do you want to run dotnet restore now? Yes3. Fully Parameterized
Provide all parameters on command line:
bash
xcons dotnet create -n dashboard-api -d "Dashboard API with real-time data"Interaction:
? Do you want to run npm install now? Yes
? Do you want to run dotnet restore now? Yes4. Non-Interactive Mode
For CI/CD or script usage:
bash
xcons dotnet create -n dashboard-api --no-interactionBehavior:
- Project name: dashboard-api
- Description: "dashboard-api .NET project" (automatic)
- npm install: Skipped
- dotnet restore: Skipped
- No questions asked
5. Direct with NPX
Without global installation:
bash
npx @xcons/cli dotnet create -n my-dotnet-widgetGenerated Project Structure
Directory Structure
dashboard-api/
├── .idea/ # IntelliJ IDEA / Rider config
│ ├── workspace.xml
│ ├── modules.xml
│ └── dashboard-api.iml
├── .vs/ # Visual Studio config (automatic)
│ └── dashboard-api/
│ └── v17/
├── dashboard-api.sln # Solution file
├── dashboard-api/ # Main project folder
│ ├── .xcon/ # XCON configuration
│ │ └── config.json # Widget build config
│ ├── Controllers/ # API Controllers
│ │ └── WeatherForecastController.cs
│ ├── Models/ # Data Models
│ │ └── WeatherForecast.cs
│ ├── Services/ # Business Logic
│ ├── src/ # Frontend Widget Source
│ │ ├── widget.ts # Widget logic
│ │ ├── widget.html # Widget template
│ │ └── widget.css # Widget styles
│ ├── wwwroot/ # Static files
│ │ └── dist/ # Built widget (created on build)
│ │ └── widget.min.js
│ ├── Program.cs # ASP.NET Core entry
│ ├── appsettings.json # App configuration
│ ├── dashboard-api.csproj # Project file
│ ├── package.json # NPM dependencies
│ ├── tsconfig.json # TypeScript config
│ └── webpack.config.js # Webpack config
├── .gitignore
└── README.mdAutomatically Generated Files
1. .xcon/config.json
json
{
"configurations": {
"provider": "",
"id": ""
},
"projectType": "dotnet",
"version": "1.0"
}Note: Provider and ID fields are left empty, must be filled by developer.
2. Solution File (dashboard-api.sln)
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dashboard-api", "dashboard-api\dashboard-api.csproj"
EndProject
Global
...
EndGlobal3. Project File (.csproj)
xml
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
</Project>4. package.json
json
{
"name": "dashboard-api",
"version": "1.0.0",
"scripts": {
"dev": "webpack --mode development --watch",
"build": "webpack --mode production"
},
"devDependencies": {
"@xcons/widget": "latest",
"typescript": "~5.5.2",
"webpack": "^5.101.3",
"webpack-cli": "^5.1.4",
"ts-loader": "^9.4.0"
}
}5. Program.cs
csharp
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Add CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseCors("AllowAll");
app.UseStaticFiles();
app.UseAuthorization();
app.MapControllers();
app.Run();6. IntelliJ IDEA Configuration
.iml file is automatically created according to widget name:
WebApplication1.iml→ renamed asdashboard-api.imlmodules.xmlfile is updatedworkspace.xmlis cleaned
Workflow
1. Creating .NET Widget
bash
# Create project
xcons dotnet create -n dashboard-api
# Navigate to solution directory
cd dashboard-api2. Installing Dependencies
Automatic installation (recommended):
bash
xcons dotnet create -n dashboard-api
# "Do you want to run npm install now?" → Yes
# "Do you want to run dotnet restore now?" → YesManual installation:
bash
cd dashboard-api # Enter project folder
npm install
dotnet restore3. Development
Backend development (Visual Studio 2022):
bash
# Open solution
dashboard-api.sln
# Or from command line
start dashboard-api.sln # Windows
open dashboard-api.sln # macOSFrontend development:
bash
cd dashboard-api # Enter project folder
# Development server
npm run dev
# Edit code
# src/widget.ts - Widget logic
# src/widget.html - Template
# src/widget.css - StylesRunning backend:
bash
cd dashboard-api
dotnet run
# Runs on https://localhost:50014. Build
Frontend build:
bash
cd dashboard-api
npm run build
# Output: wwwroot/dist/widget.min.jsBackend build:
bash
dotnet build5. Publish
With Visual Studio 2022:
- Right click on project in Solution Explorer
- Select "Publish"
- Configure publish profile
- Click "Publish" button
With command line:
bash
dotnet publish -c Release -o ./publishConfiguration Steps
1. Setting Provider
Edit .xcon/config.json file:
json
{
"configurations": {
"provider": "web", // "web" or "thingsboard"
"id": "dashboard-api-widget" // Widget ID
},
"projectType": "dotnet",
"version": "1.0"
}2. Build Settings
Full build configuration:
json
{
"configurations": {
"provider": "web",
"id": "dashboard-api-widget",
"type": "latest",
"fqn": "com.example.DashboardAPI"
},
"build": {
"entry": "widget.ts",
"sourceRoot": "src",
"outputFilename": "widget.min.js",
"outputPath": "wwwroot/dist",
"tsConfig": "tsconfig.json",
"externals": {
"axios": "axios"
}
},
"projectType": "dotnet",
"version": "1.0"
}3. Adding Backend API
Controllers/DataController.cs:
csharp
using Microsoft.AspNetCore.Mvc;
namespace DashboardApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
[HttpGet]
public IActionResult GetData()
{
var data = new
{
timestamp = DateTime.UtcNow,
value = Random.Shared.Next(0, 100)
};
return Ok(data);
}
}
}Frontend integration (src/widget.ts):
typescript
import axios from 'axios';
@Widget({
// configuration
})
export class DashboardWidget {
private apiUrl = '/api/data';
async onInit() {
await this.loadData();
}
private async loadData() {
try {
const response = await axios.get(this.apiUrl);
console.log('Data:', response.data);
} catch (error) {
console.error('API Error:', error);
}
}
}4. CORS Configuration
Program.cs:
csharp
// Add CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("WidgetPolicy", policy =>
{
policy.WithOrigins("http://localhost:4201")
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build();
app.UseCors("WidgetPolicy");
app.UseStaticFiles();
app.MapControllers();
app.Run();IDE Usage
Visual Studio 2022
Opening solution:
bash
# Windows
start dashboard-api.sln
# Or from Visual Studio
File → Open → Project/Solution → dashboard-api.slnStarting debug:
- Press F5
- Backend API starts automatically
- Swagger UI: https://localhost:5001/swagger
Publish:
- Solution Explorer → Right click on project
- Select "Publish"
- Configure profile
- Click "Publish" button
VS Code
Opening workspace:
bash
code dashboard-apiBackend debug (.vscode/launch.json):
json
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/dashboard-api/bin/Debug/net8.0/dashboard-api.dll",
"cwd": "${workspaceFolder}/dashboard-api",
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
]
}IntelliJ IDEA / Rider
Opening project:
bash
idea dashboard-api # IntelliJ IDEA
rider dashboard-api # JetBrains RiderRun/Debug configurations:
- .NET launch configuration is created automatically
- Shift+F10 - Run
- Shift+F9 - Debug
Special Scenarios
1. REST API Widget
bash
xcons dotnet create -n rest-api-widget
cd rest-api-widget/rest-api-widgetControllers/TodoController.cs:
csharp
[ApiController]
[Route("api/[controller]")]
public class TodoController : ControllerBase
{
private static List<Todo> _todos = new();
[HttpGet]
public IActionResult GetAll()
{
return Ok(_todos);
}
[HttpPost]
public IActionResult Create([FromBody] Todo todo)
{
_todos.Add(todo);
return CreatedAtAction(nameof(GetAll), todo);
}
}
public record Todo(int Id, string Title, bool Completed);.xcon/config.json:
json
{
"configurations": {
"provider": "web",
"id": "rest-api-widget"
},
"build": {
"entry": "widget.ts",
"sourceRoot": "src",
"outputFilename": "widget.min.js",
"outputPath": "wwwroot/dist",
"tsConfig": "tsconfig.json",
"externals": {
"axios": "axios"
}
},
"data": {
"additionalTypeParameters": {
"apiEndpoint": "/api/todo"
}
},
"projectType": "dotnet",
"version": "1.0"
}2. Real-time SignalR Widget
bash
xcons dotnet create -n realtime-widget
cd realtime-widget/realtime-widgetInstall SignalR:
bash
dotnet add package Microsoft.AspNetCore.SignalRHubs/DataHub.cs:
csharp
using Microsoft.AspNetCore.SignalR;
public class DataHub : Hub
{
public async Task SendData(object data)
{
await Clients.All.SendAsync("ReceiveData", data);
}
}Program.cs:
csharp
builder.Services.AddSignalR();
var app = builder.Build();
app.MapHub<DataHub>("/dataHub");Frontend (src/widget.ts):
typescript
import * as signalR from '@microsoft/signalr';
@Widget({
// configuration
})
export class RealtimeWidget {
private connection: signalR.HubConnection;
async onInit() {
this.connection = new signalR.HubConnectionBuilder()
.withUrl("/dataHub")
.build();
this.connection.on("ReceiveData", (data) => {
console.log('Real-time data:', data);
});
await this.connection.start();
}
onDestroy() {
this.connection.stop();
}
}3. Database Integration Widget
bash
xcons dotnet create -n database-widget
cd database-widget/database-widgetInstall Entity Framework:
bash
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServerData/ApplicationDbContext.cs:
csharp
using Microsoft.EntityFrameworkCore;
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options) { }
public DbSet<SensorData> SensorData { get; set; }
}
public class SensorData
{
public int Id { get; set; }
public DateTime Timestamp { get; set; }
public double Value { get; set; }
}Program.cs:
csharp
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))
);appsettings.json:
json
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=WidgetDb;Trusted_Connection=true;"
}
}Troubleshooting
Issue: Directory already exists
Error:
Error: Directory 'dashboard-api' already exists and is not emptySolution 1 - Different name:
bash
xcons dotnet create -n dashboard-api-v2Solution 2 - Delete directory:
bash
rm -rf dashboard-api
xcons dotnet create -n dashboard-apiIssue: Template download failed
Error:
Error: Failed to download template: ETIMEDOUTSolution - Check network:
bash
# Test connection
ping github.com
# Proxy settings (if needed)
npm config set proxy http://proxy:8080
npm config set https-proxy http://proxy:8080
# Try again
xcons dotnet create -n dashboard-apiIssue: npm install failed
Error:
Warning: npm install failed: EACCESSolution - Manual installation:
bash
cd dashboard-api/dashboard-api
npm installIssue: dotnet restore failed
Error:
Warning: dotnet restore failedSolution:
bash
# Check .NET SDK version
dotnet --version # Should be 6.0+
# Manual restore
cd dashboard-api/dashboard-api
dotnet restoreIssue: Visual Studio project files not updated
Problem: Visual Studio shows old project name
Solution - Manual update:
bash
cd dashboard-api
# Edit .sln file
# Change WebApplication1 → dashboard-api
# Edit .csproj file
# Update project nameBest Practices
1. Project Naming
Correct:
bash
xcons dotnet create -n dashboard-api
xcons dotnet create -n sensor-monitor
xcons dotnet create -n data-analyzerWrong:
bash
xcons dotnet create -n "Dashboard API" # No spaces
xcons dotnet create -n dashboard_api # Hyphen instead of underscore
xcons dotnet create -n DashboardAPI # Not camel case2. Output Path
Use wwwroot for .NET widgets:
json
{
"build": {
"outputPath": "wwwroot/dist" // Standard for .NET
}
}3. API Endpoint Configuration
appsettings.json:
json
{
"WidgetSettings": {
"ApiEndpoint": "/api/widget",
"CorsOrigins": ["http://localhost:4201"]
}
}.xcon/config.json:
json
{
"data": {
"additionalTypeParameters": {
"apiEndpoint": "/api/widget"
}
}
}4. Dependency Management
package.json - Frontend:
json
{
"dependencies": {
"@xcons/widget": "latest",
"axios": "^1.6.0"
},
"devDependencies": {
"typescript": "~5.5.2",
"webpack": "^5.101.3"
}
}.csproj - Backend:
xml
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>Command Output
Successful Creation
bash
$ xcons dotnet create -n dashboard-api
Creating .NET widget project...
Downloading and extracting .NET template from GitHub...
Downloading ZIP file...
ZIP file downloaded successfully
Extracting files...
Extraction completed
Moving files to target directory...
Verified 42 items in target directory
Cleaning up temporary files...
.NET template downloaded and extracted successfully
Updating .NET project files...
Renamed WebApplication1.sln to dashboard-api.sln
Renamed WebApplication1 folder to dashboard-api
Renamed WebApplication1.csproj to dashboard-api.csproj
Updated .idea/modules.xml
Updated .idea/workspace.xml
.NET project files updated successfully
Creating .xcon configuration...
.xcon/config.json created successfully
.NET project 'dashboard-api' created successfully!
Location: /Users/dev/projects/dashboard-api
? Do you want to run npm install now? Yes
Running npm install...
npm install completed successfully
? Do you want to run dotnet restore now? Yes
Running dotnet restore...
dotnet restore completed successfully
Next steps:
cd dashboard-api
npm run build
Develop your .NET widgetNon-Interactive Mode Output
bash
$ xcons dotnet create -n dashboard-api --no-interaction
Creating .NET widget project...
Downloading and extracting .NET template from GitHub...
.NET template downloaded and extracted successfully
Updating .NET project files...
.NET project files updated successfully
Creating .xcon configuration...
.xcon/config.json created successfully
.NET project 'dashboard-api' created successfully!
Location: /Users/dev/projects/dashboard-api
Skipping npm install due to --no-interaction flag
Skipping dotnet restore due to --no-interaction flag
Next steps:
cd dashboard-api
npm install
dotnet restore
npm run build
Develop your .NET widgetFrequently Asked Questions
Q: What is the difference between .NET widget and TypeScript widget? A: .NET widget comes with backend API. TypeScript widget is frontend only.
Q: Can I develop without Visual Studio? A: Yes, you can develop with VS Code or Rider. However, Visual Studio 2022 offers the best .NET experience.
Q: How do frontend and backend run simultaneously? A:
bash
# Terminal 1 - Backend
cd dashboard-api
dotnet run
# Terminal 2 - Frontend
cd dashboard-api
npm run devQ: I skipped npm install, how do I install it later? A: Go to project folder and run npm install:
bash
cd dashboard-api/dashboard-api
npm installQ: Why is wwwroot folder important? A: ASP.NET Core static files middleware serves files only from wwwroot. Widget output must be written here.
Q: Why are .xcon/config.json provider and id fields empty? A: Developer must decide which platform (web/thingsboard) to create widget for and configure appropriate settings.
.NET widget creation ready! You can start developing.