Skip to content

egarim/XafBlazorViewItemUrlConfiguration

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

XAF Blazor ViewItem URL Configuration

How to make XAF ViewItems accessible via direct URL with parameters in Blazor

This project demonstrates how to expose XAF ViewItems as standalone pages with URL parameter configuration, plus REST API access - all using the same component.

🎯 The Problem This Solves

Traditional XAF ViewItems:

  • ❌ Only accessible after login + navigation
  • ❌ No direct URL access
  • ❌ Can't share links to specific views
  • ❌ No URL parameters

This Solution:

  • βœ… Direct URL access: /chat?message=Hello
  • βœ… URL parameters configure ViewItem state
  • βœ… Shareable links
  • βœ… Embeddable in other apps
  • βœ… REST API for programmatic access

πŸš€ Three Integration Approaches

1️⃣ Traditional XAF ViewItem (Baseline)

What: Standard XAF ViewItem embedded in application Access: Login β†’ Navigate β†’ View Use case: Internal business app with full XAF security

https://yourapp.com/ β†’ Login β†’ Navigate to "AI Chat"

2️⃣ URL-Configurable Standalone Page (β˜… Main Feature)

What: Blazor page exposing ViewItem via direct URL Access: Direct URL with parameters Use case: Shareable links, bookmarks, QR codes, embeds

Examples:

https://yourapp.com/chat
https://yourapp.com/chat?message=Hello
https://yourapp.com/chat?message=Show order 123&context=order123

URL Parameters:

  • message - Pre-populate initial message
  • context - Pass context data (orderId, userId, etc.)

3️⃣ REST API Endpoint (Bonus)

What: HTTP API for programmatic access Access: POST request with JSON Use case: Mobile apps, external systems, automation

Endpoint:

POST https://yourapp.com/api/chat
{
  "message": "List all orders",
  "context": { "userId": "123" }
}

πŸ“– Example: AI Chat ViewItem

This demo uses an AI Chat component (GitHub Copilot SDK) as the ViewItem example, but the URL configuration pattern works for ANY XAF ViewItem.

The same approach can be used for:

  • Order detail views β†’ /order?id=123
  • Customer profiles β†’ /customer?id=456&tab=orders
  • Reports β†’ /report?type=sales&month=2026-02
  • Dashboard widgets β†’ /dashboard?widget=sales&period=today

πŸ—οΈ How It Works

Architecture

Traditional XAF ViewItem (secured, full XAF)
         ↓
    Shared Component
   (CopilotChat.razor)
         ↓
         β”œβ”€β”€β†’ Standalone Page (/chat) ← URL Parameters
         └──→ REST API (/api/chat) ← JSON Request

Key Components

1. Shared ViewItem Component

XafBlazorViewItemUrlConfiguration.Blazor.Server/
└── Editors/CopilotChatViewItem/
    β”œβ”€β”€ CopilotChat.razor              ← Reusable component
    └── CopilotChatViewItemBlazor.cs   ← XAF ViewItem wrapper

2. Standalone Page with URL Parameters

XafBlazorViewItemUrlConfiguration.Blazor.Server/
└── Pages/
    └── Chat.razor                     ← URL-accessible page

Code snippet:

@page "/chat"
@page "/chat/{InitialMessage?}"

@code {
    [Parameter]
    [SupplyParameterFromQuery(Name = "message")]
    public string? InitialMessage { get; set; }

    [Parameter]
    [SupplyParameterFromQuery(Name = "context")]
    public string? Context { get; set; }
}

3. REST API Controller

XafBlazorViewItemUrlConfiguration.WebApi/
└── Controllers/
    └── ChatController.cs              ← HTTP endpoint

πŸš€ Quick Start

Prerequisites

  • .NET 9.0 SDK
  • DevExpress XAF license
  • GitHub Copilot API key (for this demo)

1. Clone & Restore

git clone https://github.com/egarim/XafBlazorViewItemUrlConfiguration.git
cd XafBlazorViewItemUrlConfiguration
dotnet restore XafBlazorViewItemUrlConfiguration.sln

2. Configure API Key

Edit appsettings.json in both projects:

{
  "GitHubCopilot": {
    "ApiKey": "your-copilot-api-key",
    "Model": "gpt-4o"
  }
}

3. Run

# Terminal 1: Blazor Server (port 5001)
cd XafBlazorViewItemUrlConfiguration.Blazor.Server
dotnet run

# Terminal 2: Web API (port 5002)
cd XafBlazorViewItemUrlConfiguration.WebApi
dotnet run

4. Test

Traditional XAF:

https://localhost:5001
Login: Admin / (empty password)
Navigate to: "Copilot Chat"

Direct URL Access:

https://localhost:5001/chat
https://localhost:5001/chat?message=Hello
https://localhost:5001/chat?message=Show order&context=order123

REST API:

curl -X POST https://localhost:5002/api/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Hello, who are you?"}'

🎨 Adapting for Your ViewItems

Step 1: Extract Your ViewItem as a Component

Before (XAF-only):

[ViewItem(typeof(IModelMyViewItem))]
public class MyViewItemBlazor : ViewItem
{
    // XAF-specific code
}

After (Reusable Component):

// 1. Create standalone component
// MyComponent.razor
<div class="my-component">
    @* Your ViewItem UI *@
</div>

@code {
    [Parameter]
    public string? InitialData { get; set; }
}

// 2. Wrap in XAF ViewItem
public class MyViewItemBlazor : ViewItem, IComponentContentHolder
{
    RenderFragment IComponentContentHolder.ComponentContent => builder =>
    {
        builder.OpenComponent<MyComponent>(0);
        builder.CloseComponent();
    };
}

Step 2: Create Standalone Page

// Pages/MyView.razor
@page "/myview"
@page "/myview/{Id?}"

<MyComponent InitialData="@Id" />

@code {
    [Parameter]
    [SupplyParameterFromQuery(Name = "id")]
    public string? Id { get; set; }
}

Step 3: Add API Endpoint (Optional)

[ApiController]
[Route("api/myview")]
public class MyViewController : ControllerBase
{
    [HttpPost]
    public IActionResult Process([FromBody] MyRequest request)
    {
        // Process and return data
        return Ok(new MyResponse { ... });
    }
}

πŸ“Š Comparison: Before vs After

Feature Traditional XAF With URL Config
Login Required βœ… Always βš™οΈ Optional
Direct URL Access ❌ No βœ… Yes
Shareable Links ❌ No βœ… Yes
URL Parameters ❌ No βœ… Yes
Embeddable ❌ No βœ… Yes
REST API ❌ No βœ… Yes
XAF Security βœ… Full βš™οΈ Optional

🎯 Real-World Use Cases

1. Customer Order Links

Problem: Customer calls: "Where's my order?" Solution: Send them a direct link

https://yourapp.com/order?id=12345&email=customer@example.com

Customer sees order status without login.

2. QR Code on Receipts

Problem: Want customers to access support chat Solution: Print QR code linking to chat with order context

https://yourapp.com/support?order=12345&store=downtown

3. Email Action Links

Problem: Email says "Approve expense report #789" Solution: Link directly to approval view

https://yourapp.com/approve?type=expense&id=789&token=...

4. Mobile App Integration

Problem: Mobile app needs to access XAF functionality Solution: Call REST API

var response = await httpClient.PostAsJsonAsync(
    "https://yourapp.com/api/order",
    new { orderId = 123 }
);

5. Telegram/Discord Bot

Problem: Users want to query data via chat Solution: Bot calls your API

response = requests.post("https://yourapp.com/api/chat", 
    json={"message": "Show today's orders"})

πŸ”’ Security Considerations

Public Access (Standalone Page)

// Chat.razor - No authentication
@page "/chat"
<MyComponent />

Token-Based Auth

// Chat.razor - Require token
@page "/chat"
@attribute [Authorize]
<MyComponent />

API Key Auth

// ChatController.cs
[ApiKey] // Custom attribute
public class ChatController : ControllerBase
{
    // ...
}

XAF Security Integration

// Keep XAF security for ViewItem, public for standalone
if (User.Identity?.IsAuthenticated == true)
{
    // Use XAF security
}
else
{
    // Limited public access
}

πŸ“ Project Structure

XafBlazorViewItemUrlConfiguration/
β”œβ”€β”€ XafBlazorViewItemUrlConfiguration.Blazor.Server/
β”‚   β”œβ”€β”€ Editors/
β”‚   β”‚   └── CopilotChatViewItem/
β”‚   β”‚       β”œβ”€β”€ CopilotChat.razor              ← Shared component
β”‚   β”‚       └── CopilotChatViewItemBlazor.cs   ← XAF ViewItem
β”‚   └── Pages/
β”‚       └── Chat.razor                          ← URL-accessible page β˜…
β”‚
β”œβ”€β”€ XafBlazorViewItemUrlConfiguration.WebApi/
β”‚   └── Controllers/
β”‚       └── ChatController.cs                   ← REST API β˜…
β”‚
β”œβ”€β”€ XafBlazorViewItemUrlConfiguration.Module/
β”‚   └── Services/
β”‚       └── CopilotChatService.cs              ← Business logic
β”‚
└── README.md                                   ← You are here

πŸ§ͺ Testing URLs

Basic Access

https://localhost:5001/chat

Pre-populated Message

https://localhost:5001/chat?message=List all orders

With Context

https://localhost:5001/chat?message=Show details&context=order123

Multiple Parameters

https://localhost:5001/chat?message=Hello&context=user:456,order:789

πŸ’‘ Tips & Best Practices

1. URL-Friendly Parameter Encoding

// Good
var url = $"/chat?message={Uri.EscapeDataString("Show order #123")}";
// Result: /chat?message=Show%20order%20%23123

// Bad
var url = $"/chat?message=Show order #123"; // Breaks with special chars

2. Deep Linking Pattern

// Support both formats
@page "/order/{Id}"                    // /order/123
[SupplyParameterFromQuery(Name = "id")] // /order?id=123

3. State Preservation

// Save state to URL when it changes
protected override void OnParametersSet()
{
    NavigationManager.NavigateTo(
        $"/chat?message={CurrentMessage}&context={CurrentContext}",
        replace: true
    );
}

4. Share Button Implementation

<button @onclick="CopyShareLink">πŸ“‹ Copy Link</button>

@code {
    async Task CopyShareLink()
    {
        var url = $"{NavigationManager.BaseUri}chat?message={Message}";
        await JSRuntime.InvokeVoidAsync("navigator.clipboard.writeText", url);
    }
}

πŸ“š Related Articles

This project is inspired by:


🀝 Contributing

Contributions welcome! Open an issue or PR.


πŸ“„ License

MIT License - see LICENSE.txt


πŸ”— Links


Made with ❀️ by Joche Ojeda

Tags: xaf, devexpress, blazor, url-configuration, viewitem, deep-linking, rest-api, copilot

About

How to make XAF ViewItems accessible via direct URL with parameters in Blazor. Demo: AI Chat accessible as /chat?message=Hello

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors