Skip to content

.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

OptionShorthandTypeDefaultDescription
--name <name>-nstring-.NET project name
--description <desc>-dstring-Project description
--no-interaction-flagfalseInteractive questions are not asked

Usage Examples

Simplest usage - command interactively asks for required information:

bash
xcons dotnet create

Interaction:

? .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? Yes

2. With Name Parameter

Provide project name as parameter:

bash
xcons dotnet create -n dashboard-api

Interaction:

? .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? Yes

3. 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? Yes

4. Non-Interactive Mode

For CI/CD or script usage:

bash
xcons dotnet create -n dashboard-api --no-interaction

Behavior:

  • 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-widget

Generated 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.md

Automatically 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
    ...
EndGlobal

3. 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 as dashboard-api.iml
  • modules.xml file is updated
  • workspace.xml is cleaned

Workflow

1. Creating .NET Widget

bash
# Create project
xcons dotnet create -n dashboard-api

# Navigate to solution directory
cd dashboard-api

2. 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?" → Yes

Manual installation:

bash
cd dashboard-api  # Enter project folder
npm install
dotnet restore

3. 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   # macOS

Frontend 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 - Styles

Running backend:

bash
cd dashboard-api
dotnet run
# Runs on https://localhost:5001

4. Build

Frontend build:

bash
cd dashboard-api
npm run build
# Output: wwwroot/dist/widget.min.js

Backend build:

bash
dotnet build

5. Publish

With Visual Studio 2022:

  1. Right click on project in Solution Explorer
  2. Select "Publish"
  3. Configure publish profile
  4. Click "Publish" button

With command line:

bash
dotnet publish -c Release -o ./publish

Configuration 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.sln

Starting debug:

  1. Press F5
  2. Backend API starts automatically
  3. Swagger UI: https://localhost:5001/swagger

Publish:

  1. Solution Explorer → Right click on project
  2. Select "Publish"
  3. Configure profile
  4. Click "Publish" button

VS Code

Opening workspace:

bash
code dashboard-api

Backend 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 Rider

Run/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-widget

Controllers/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-widget

Install SignalR:

bash
dotnet add package Microsoft.AspNetCore.SignalR

Hubs/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-widget

Install Entity Framework:

bash
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

Data/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 empty

Solution 1 - Different name:

bash
xcons dotnet create -n dashboard-api-v2

Solution 2 - Delete directory:

bash
rm -rf dashboard-api
xcons dotnet create -n dashboard-api

Issue: Template download failed

Error:

Error: Failed to download template: ETIMEDOUT

Solution - 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-api

Issue: npm install failed

Error:

Warning: npm install failed: EACCES

Solution - Manual installation:

bash
cd dashboard-api/dashboard-api
npm install

Issue: dotnet restore failed

Error:

Warning: dotnet restore failed

Solution:

bash
# Check .NET SDK version
dotnet --version  # Should be 6.0+

# Manual restore
cd dashboard-api/dashboard-api
dotnet restore

Issue: 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 name

Best Practices

1. Project Naming

Correct:

bash
xcons dotnet create -n dashboard-api
xcons dotnet create -n sensor-monitor
xcons dotnet create -n data-analyzer

Wrong:

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 case

2. 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 widget

Non-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 widget

Frequently 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 dev

Q: 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 install

Q: 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.