You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Prefer secure flows (Client Secret or Certificate) in production; avoid username/password.
75
95
76
96
### 3. Create Dataverse Schema
77
97
78
98
Create the following entities in your Dataverse environment:
79
99
80
100
**Order Entity (`new_order`)**:
101
+
81
102
-`new_customerid` (Customer lookup to Account)
82
103
-`new_orderdate` (Date)
83
104
-`new_ordernumber` (Text)
@@ -110,7 +131,7 @@ The API will be available at `https://localhost:7000` with Swagger UI at the roo
110
131
111
132
### Unit Tests
112
133
113
-
Run the shared validation tests:
134
+
Run the shared validation tests (currently 38 passing tests covering boundaries, error paths, and success cases):
114
135
115
136
```bash
116
137
cd tests/Shared.Domain.Tests
@@ -145,6 +166,7 @@ curl -X POST https://localhost:7000/api/orders/validate \
145
166
### Plugin Testing
146
167
147
168
Create an order through:
169
+
148
170
- Dataverse forms
149
171
- Power Apps
150
172
- Power Automate
@@ -269,6 +291,15 @@ public async Task<IActionResult> CreateOrder(CreateOrderRequest request)
269
291
-**Integration test both paths** (plugin and API) against actual Dataverse
270
292
-**Performance test** with realistic data volumes
271
293
294
+
## 🧬 Multi-Targeting Rationale
295
+
296
+
`Shared.Domain` targets both `net8.0` and `netstandard2.0` so it can be consumed by:
297
+
298
+
- Modern .NET 8 API (leveraging latest runtime features)
299
+
- Legacy `net472` plugin via `netstandard2.0` surface (compatible with classic Dataverse plugin host)
300
+
301
+
Records are preserved by adding an `IsExternalInit` polyfill for the `netstandard2.0` target, avoiding refactors to classes while keeping modern C# expressiveness.
302
+
272
303
## 📚 Key Files Reference
273
304
274
305
| File | Purpose |
@@ -279,6 +310,54 @@ public async Task<IActionResult> CreateOrder(CreateOrderRequest request)
279
310
|`Api.Orders/Controllers/OrdersController.cs`|**API controller** - validates before sending to Dataverse |
280
311
|`Plugins.Dataverse/Adapters/DataverseOrderRulesData.cs`|**Plugin data adapter** - implements IOrderRulesData using IOrganizationService |
281
312
|`Api.Orders/Adapters/DataverseOrderRulesDataForApp.cs`|**API data adapter** - implements IOrderRulesData using ServiceClient |
313
+
|`Tests/Shared.Domain.Tests/CreateOrderValidatorAdditionalTests.cs`|**Extended test coverage** for boundaries & edge cases |
314
+
315
+
## 🔒 Security & Secrets
316
+
317
+
Do not commit real credentials. Connection string is externalized. Recommended improvements:
318
+
319
+
- Use Azure Key Vault or environment variables in hosting environment
320
+
- Store secrets only in CI secret store (GitHub Actions Secrets)
321
+
- Enforce HTTPS and strict TLS settings
322
+
- Add static code analysis (CodeQL)
323
+
324
+
## 🤖 CI/CD (Suggested)
325
+
326
+
Add a GitHub Actions workflow `.github/workflows/ci.yml`:
327
+
328
+
- Restore -> Build (Release) -> Test -> (Optional) Publish test & coverage results
329
+
- Fail build on test failures
330
+
331
+
Optional steps:
332
+
333
+
- Cache NuGet (`actions/cache`)
334
+
- Upload coverage to Codecov
335
+
336
+
## 🗺️ Roadmap (Ideas)
337
+
338
+
- Implement real order line entity persistence & retrieval
339
+
- Add credit limit validation using customer financials
340
+
- Introduce caching layer for product/customer lookups
341
+
- Provide integration test project hitting a Dataverse sandbox (flagged to skip in CI without env vars)
342
+
- Add OpenAPI schema filtering for validation error codes
343
+
- Provide sample Power Automate flow invoking API
344
+
345
+
## ⚠️ Troubleshooting Additions
346
+
347
+
If environment variable not picked up:
348
+
349
+
- Ensure terminal session set it before running `dotnet run`
350
+
- On Windows, consider using System Environment Variables if launching via IDE
351
+
352
+
If plugin cannot load assembly:
353
+
354
+
- Confirm target framework remains `net472`
355
+
- Ensure no accidental reference to `net8.0`-only APIs in plugin project
356
+
357
+
If validation differs between API and plugin:
358
+
359
+
- Check both adapters (`DataverseOrderRulesData` vs `DataverseOrderRulesDataForApp`) return matching data for same IDs
360
+
282
361
283
362
## 🤝 Contributing
284
363
@@ -302,7 +381,8 @@ This project is licensed under the MIT License - see the LICENSE file for detail
302
381
303
382
**Validation not working**: Ensure both adapters implement IOrderRulesData correctly and return consistent results.
304
383
305
-
**Performance issues**:
384
+
**Performance issues**:
385
+
306
386
- Use column sets to limit data retrieval
307
387
- Implement caching for reference data
308
388
- Avoid N+1 query patterns
@@ -312,4 +392,4 @@ This project is licensed under the MIT License - see the LICENSE file for detail
312
392
- Check the unit tests for usage examples
313
393
- Review the Swagger documentation at the API root
314
394
- Enable detailed logging to troubleshoot validation failures
0 commit comments