Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
This file explains how Visual Studio created the project.

The following steps were used to generate this project:
- Create new ASP\.NET Core Web API project.
- Update project file to add a reference to the frontend project and set SPA properties.
- Update `launchSettings.json` to register the SPA proxy as a startup assembly.
- Add project to the startup projects list.
- Write this file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using Grid_EntityFramework.Server.Data;
using Grid_EntityFramework.Server.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Syncfusion.EJ2.Base;

namespace Grid_EntityFramework.Server.Controllers
{
[Route("api/[controller]")]
public class TicketsController : ControllerBase
{
private readonly TicketsDbContext _db;

public TicketsController(TicketsDbContext db)
{
_db = db;
}

// READ
[HttpPost("url")]
public IActionResult UrlDataSource([FromBody] DataManagerRequest dm)
{
IQueryable<Ticket> query = _db.Tickets.AsNoTracking();
var op = new DataOperations();

if (dm.Search?.Count > 0)
query = op.PerformSearching(query, dm.Search).Cast<Ticket>().AsQueryable();

if (dm.Where?.Count > 0)
query = op.PerformFiltering(query, dm.Where, dm.Where[0].Operator)
.Cast<Ticket>()
.AsQueryable();

if (dm.Sorted?.Count > 0)
query = op.PerformSorting(query, dm.Sorted).Cast<Ticket>().AsQueryable();
else
query = query.OrderBy(t => t.TicketId);

var count = query.Count();

if (dm.Skip > 0)
query = query.Skip(dm.Skip);

if (dm.Take > 0)
query = query.Take(dm.Take);

return dm.RequiresCounts
? Ok(new { result = query.ToList(), count })
: Ok(query.ToList());
}

// CREATE
[HttpPost("insert")]
public IActionResult Insert([FromBody] CRUDModel<Ticket> value)
{
var ticket = value.Value;

// Identity handled like MVC
ticket.TicketId = 0;

_db.Tickets.Add(ticket);
_db.SaveChanges();

return Ok(ticket);
}

// UPDATE
[HttpPost("update")]
public IActionResult Update([FromBody] CRUDModel<Ticket> value)
{
var ticket = value.Value;

_db.Entry(ticket).State = EntityState.Modified;
_db.SaveChanges();

return Ok(ticket);
}

// DELETE
[HttpPost("remove")]
public IActionResult Remove([FromBody] CRUDModel<Ticket> value)
{
var key = Convert.ToInt32(value.Key);
var ticket = _db.Tickets.First(t => t.TicketId == key);

_db.Tickets.Remove(ticket);
_db.SaveChanges();

return Ok(value);
}

// BATCH
[HttpPost("batch")]
public IActionResult Batch([FromBody] CRUDModel<Ticket> value)
{
if (value.Changed != null)
{
foreach (var ticket in value.Changed)
{
_db.Tickets.Attach(ticket);
_db.Entry(ticket).State = EntityState.Modified;
}
}

if (value.Added != null)
{
foreach (var ticket in value.Added)
{
ticket.TicketId = 0;
_db.Tickets.Add(ticket);
}
}

if (value.Deleted != null)
{
foreach (var ticket in value.Deleted)
{
var existing = _db.Tickets.Find(ticket.TicketId);
if (existing != null)
_db.Tickets.Remove(existing);
}
}

_db.SaveChanges();
return Ok(value);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// File: Data/TicketsDbContext.cs
using Grid_EntityFramework.Server.Models;
using Microsoft.EntityFrameworkCore;

namespace Grid_EntityFramework.Server.Data
{
public class TicketsDbContext(DbContextOptions<TicketsDbContext> options) : DbContext(options)
{
public DbSet<Ticket> Tickets => Set<Ticket>();

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<Ticket>();

// Table and Schema
entity.ToTable("Tickets", "dbo");

// PK
entity.HasKey(e => e.TicketId);

// Identity (handled by [DatabaseGenerated] attribute, but we can be explicit)
entity.Property(e => e.TicketId).ValueGeneratedOnAdd();

// Column configs (equivalent to your EF6 constraints)
entity.Property(e => e.PublicTicketId).HasMaxLength(50).IsRequired();
entity.HasIndex(e => e.PublicTicketId).IsUnique(); // matches your EF6 unique index

entity.Property(e => e.Title).HasMaxLength(200);
entity.Property(e => e.Description).HasColumnType("text"); // or nvarchar(max)
entity.Property(e => e.Category).HasMaxLength(100);
entity.Property(e => e.Department).HasMaxLength(100);
entity.Property(e => e.Assignee).HasMaxLength(100);
entity.Property(e => e.CreatedBy).HasMaxLength(100);
entity.Property(e => e.Status).HasMaxLength(50).IsRequired();
entity.Property(e => e.Priority).HasMaxLength(50).IsRequired();

entity.Property(e => e.ResponseDue).HasColumnType("datetime2");
entity.Property(e => e.DueDate).HasColumnType("datetime2");
entity.Property(e => e.CreatedAt).HasColumnType("datetime2").IsRequired();
entity.Property(e => e.UpdatedAt).HasColumnType("datetime2").IsRequired();

base.OnModelCreating(modelBuilder);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>disable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<SpaRoot>..\grid_entityframework.client</SpaRoot>
<SpaProxyLaunchCommand>npm start</SpaProxyLaunchCommand>
<SpaProxyServerUrl>https://localhost:57606</SpaProxyServerUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.2" />
<PackageReference Include="Microsoft.AspNetCore.SpaProxy">
<Version>8.*-*</Version>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="Syncfusion.EJ2.AspNet.Core" Version="32.1.25" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\grid_entityframework.client\grid_entityframework.client.esproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>https</ActiveDebugProfile>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@Grid_EntityFramework.Server_HostAddress = http://localhost:5018

GET {{Grid_EntityFramework.Server_HostAddress}}/weatherforecast/
Accept: application/json

###
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// File: Models/Ticket.cs
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Grid_EntityFramework.Server.Models
{
[Table("Tickets", Schema = "dbo")]
public class Ticket
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TicketId { get; set; }

[Required, MaxLength(50)]
public string PublicTicketId { get; set; }

[MaxLength(200)]
public string Title { get; set; }

// EF Core: prefer NVARCHAR(MAX) instead of deprecated TEXT.
// We'll keep column type from your EF6 note if you must match legacy schema:
[Column(TypeName = "text")] // Consider changing to nvarchar(max) for modern SQL Server
public string Description { get; set; }

[MaxLength(100)]
public string Category { get; set; }

[MaxLength(100)]
public string Department { get; set; }

[MaxLength(100)]
public string Assignee { get; set; }

[MaxLength(100)]
public string CreatedBy { get; set; }

[Required, MaxLength(50)]
public string Status { get; set; } = "Open";

[Required, MaxLength(50)]
public string Priority { get; set; } = "Medium";

[Column(TypeName = "datetime2")]
public DateTime? ResponseDue { get; set; }

[Column(TypeName = "datetime2")]
public DateTime? DueDate { get; set; }

[Required, Column(TypeName = "datetime2")]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;

[Required, Column(TypeName = "datetime2")]
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// File: Program.cs
using Grid_EntityFramework.Server.Data;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;

var builder = WebApplication.CreateBuilder(args);

builder
.Services.AddControllers()
.AddNewtonsoftJson(o =>
{
// Key setting: do not try to set null into value types (int)
o.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
// Optional hardening:
// o.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore;
});

// EF Core SQL Server
builder.Services.AddDbContext<TicketsDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("TicketsDb"))
);

builder.Services.AddControllers();

// CORS if you call from Angular dev server
builder.Services.AddCors(opts =>
{
opts.AddPolicy("dev", p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});

var app = builder.Build();
app.UseCors("dev");
app.MapControllers();
app.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:57542",
"sslPort": 44378
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5018",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7097;http://localhost:5018",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
}
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"ConnectionStrings": {
"TicketsDb": "Server=localhost;Database=TicketsDb;Trusted_Connection=True;TrustServerCertificate=True;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
Loading