mirror of
https://github.com/chsakell/aspnet-core-signalr-angular.git
synced 2025-12-22 17:27:48 +00:00
added Data, Models, EntityFramework
This commit is contained in:
@@ -5,27 +5,37 @@ using System.Threading.Tasks;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.SignalR.Infrastructure;
|
using Microsoft.AspNetCore.SignalR.Infrastructure;
|
||||||
using LiveGameFeed.Hubs;
|
using LiveGameFeed.Hubs;
|
||||||
|
using LiveGameFeed.Data.Abstract;
|
||||||
|
using LiveGameFeed.Models;
|
||||||
|
|
||||||
namespace LiveGameFeed.Controllers
|
namespace LiveGameFeed.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class FeedsController : ApiHubController<Broadcaster>
|
public class FeedsController : ApiHubController<Broadcaster>
|
||||||
{
|
{
|
||||||
public FeedsController(IConnectionManager signalRConnectionManager)
|
IFeedRepository _feedRepository;
|
||||||
: base(signalRConnectionManager) { }
|
public FeedsController(
|
||||||
|
IConnectionManager signalRConnectionManager,
|
||||||
|
IFeedRepository feedRepository)
|
||||||
|
: base(signalRConnectionManager)
|
||||||
|
{
|
||||||
|
_feedRepository = feedRepository;
|
||||||
|
}
|
||||||
|
|
||||||
// GET api/values
|
// GET api/values
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IEnumerable<string> Get()
|
public IEnumerable<Feed> Get()
|
||||||
{
|
{
|
||||||
return new string[] { "value1", "value2" };
|
IEnumerable<Feed> _feeds = _feedRepository.GetAll();
|
||||||
|
|
||||||
|
return _feeds;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/values/5
|
// GET api/values/5
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public string Get(int id)
|
public Feed Get(int id)
|
||||||
{
|
{
|
||||||
return "value";
|
return _feedRepository.GetSingle(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST api/values
|
// POST api/values
|
||||||
|
|||||||
25
Data/Abstract/IEntityBaseRepository.cs
Normal file
25
Data/Abstract/IEntityBaseRepository.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using LiveGameFeed.Models;
|
||||||
|
|
||||||
|
namespace LiveGameFeed.Data.Abstract
|
||||||
|
{
|
||||||
|
public interface IEntityBaseRepository<T> where T : class, IEntityBase, new()
|
||||||
|
{
|
||||||
|
IEnumerable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties);
|
||||||
|
IEnumerable<T> GetAll();
|
||||||
|
int Count();
|
||||||
|
T GetSingle(int id);
|
||||||
|
T GetSingle(Expression<Func<T, bool>> predicate);
|
||||||
|
T GetSingle(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties);
|
||||||
|
IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate);
|
||||||
|
void Add(T entity);
|
||||||
|
void Update(T entity);
|
||||||
|
void Delete(T entity);
|
||||||
|
void DeleteWhere(Expression<Func<T, bool>> predicate);
|
||||||
|
void Commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Data/Abstract/IRepositories.cs
Normal file
13
Data/Abstract/IRepositories.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LiveGameFeed.Models;
|
||||||
|
|
||||||
|
namespace LiveGameFeed.Data.Abstract
|
||||||
|
{
|
||||||
|
public interface IMatchRepository : IEntityBaseRepository<Match> { }
|
||||||
|
|
||||||
|
public interface IFeedRepository : IEntityBaseRepository<Feed> { }
|
||||||
|
|
||||||
|
}
|
||||||
36
Data/LiveGameContext.cs
Normal file
36
Data/LiveGameContext.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LiveGameFeed.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
|
||||||
|
namespace LiveGameFeed.Data
|
||||||
|
{
|
||||||
|
public class LiveGameContext : DbContext
|
||||||
|
{
|
||||||
|
public DbSet<Match> Matches { get; set; }
|
||||||
|
public DbSet<Feed> Feeds { get; set; }
|
||||||
|
|
||||||
|
public LiveGameContext(DbContextOptions options) : base(options) { }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
|
||||||
|
{
|
||||||
|
relationship.DeleteBehavior = DeleteBehavior.Restrict;
|
||||||
|
}
|
||||||
|
|
||||||
|
modelBuilder.Entity<Match>()
|
||||||
|
.ToTable("Match");
|
||||||
|
|
||||||
|
modelBuilder.Entity<Feed>()
|
||||||
|
.ToTable("Feed");
|
||||||
|
|
||||||
|
modelBuilder.Entity<Feed>()
|
||||||
|
.Property(f => f.MatchId)
|
||||||
|
.IsRequired();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
74
Data/LiveGameDbInitializer.cs
Normal file
74
Data/LiveGameDbInitializer.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LiveGameFeed.Models;
|
||||||
|
|
||||||
|
namespace LiveGameFeed.Data
|
||||||
|
{
|
||||||
|
public class LiveGameDbInitializer
|
||||||
|
{
|
||||||
|
private static LiveGameContext context;
|
||||||
|
public static void Initialize(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
context = (LiveGameContext)serviceProvider.GetService(typeof(LiveGameContext));
|
||||||
|
|
||||||
|
InitializeSchedules();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InitializeSchedules()
|
||||||
|
{
|
||||||
|
if (!context.Matches.Any())
|
||||||
|
{
|
||||||
|
Match match_01 = new Match
|
||||||
|
{
|
||||||
|
Host = "Panathinaikos",
|
||||||
|
Guest = "Olimpiakos",
|
||||||
|
HostScore = 3,
|
||||||
|
GuestScore = 1,
|
||||||
|
MatchDate = DateTime.Now,
|
||||||
|
League = "FootballLeauge",
|
||||||
|
Feeds = new List<Feed>
|
||||||
|
{
|
||||||
|
new Feed()
|
||||||
|
{
|
||||||
|
Description = "Match started",
|
||||||
|
MatchId = 1
|
||||||
|
},
|
||||||
|
new Feed()
|
||||||
|
{
|
||||||
|
Description = "Goal for Panathinaikos",
|
||||||
|
MatchId = 1
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Match match_02 = new Match
|
||||||
|
{
|
||||||
|
Host = "Real Madrit FC",
|
||||||
|
Guest = "Barchelona",
|
||||||
|
HostScore = 5,
|
||||||
|
GuestScore = 3,
|
||||||
|
MatchDate = DateTime.Now,
|
||||||
|
League = "Spanish League",
|
||||||
|
Feeds = new List<Feed>
|
||||||
|
{
|
||||||
|
new Feed()
|
||||||
|
{
|
||||||
|
Description = "Match started",
|
||||||
|
MatchId = 2
|
||||||
|
},
|
||||||
|
new Feed()
|
||||||
|
{
|
||||||
|
Description = "Goal for Real Madrid",
|
||||||
|
MatchId = 2
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
context.Matches.Add(match_01); context.Matches.Add(match_02);
|
||||||
|
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
102
Data/Repositories/EntityBaseRepository.cs
Normal file
102
Data/Repositories/EntityBaseRepository.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||||
|
using LiveGameFeed.Data.Abstract;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LiveGameFeed.Models;
|
||||||
|
|
||||||
|
namespace LiveGameFeed.Data.Repositories
|
||||||
|
{
|
||||||
|
public class EntityBaseRepository<T> : IEntityBaseRepository<T>
|
||||||
|
where T : class, IEntityBase, new()
|
||||||
|
{
|
||||||
|
|
||||||
|
private LiveGameContext _context;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public EntityBaseRepository(LiveGameContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
public virtual IEnumerable<T> GetAll()
|
||||||
|
{
|
||||||
|
return _context.Set<T>().AsEnumerable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual int Count()
|
||||||
|
{
|
||||||
|
return _context.Set<T>().Count();
|
||||||
|
}
|
||||||
|
public virtual IEnumerable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties)
|
||||||
|
{
|
||||||
|
IQueryable<T> query = _context.Set<T>();
|
||||||
|
foreach (var includeProperty in includeProperties)
|
||||||
|
{
|
||||||
|
query = query.Include(includeProperty);
|
||||||
|
}
|
||||||
|
return query.AsEnumerable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetSingle(int id)
|
||||||
|
{
|
||||||
|
return _context.Set<T>().FirstOrDefault(x => x.Id == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetSingle(Expression<Func<T, bool>> predicate)
|
||||||
|
{
|
||||||
|
return _context.Set<T>().FirstOrDefault(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetSingle(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties)
|
||||||
|
{
|
||||||
|
IQueryable<T> query = _context.Set<T>();
|
||||||
|
foreach (var includeProperty in includeProperties)
|
||||||
|
{
|
||||||
|
query = query.Include(includeProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Where(predicate).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate)
|
||||||
|
{
|
||||||
|
return _context.Set<T>().Where(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Add(T entity)
|
||||||
|
{
|
||||||
|
EntityEntry dbEntityEntry = _context.Entry<T>(entity);
|
||||||
|
_context.Set<T>().Add(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Update(T entity)
|
||||||
|
{
|
||||||
|
EntityEntry dbEntityEntry = _context.Entry<T>(entity);
|
||||||
|
dbEntityEntry.State = EntityState.Modified;
|
||||||
|
}
|
||||||
|
public virtual void Delete(T entity)
|
||||||
|
{
|
||||||
|
EntityEntry dbEntityEntry = _context.Entry<T>(entity);
|
||||||
|
dbEntityEntry.State = EntityState.Deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void DeleteWhere(Expression<Func<T, bool>> predicate)
|
||||||
|
{
|
||||||
|
IEnumerable<T> entities = _context.Set<T>().Where(predicate);
|
||||||
|
|
||||||
|
foreach(var entity in entities)
|
||||||
|
{
|
||||||
|
_context.Entry<T>(entity).State = EntityState.Deleted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Commit()
|
||||||
|
{
|
||||||
|
_context.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Data/Repositories/FeedRepository.cs
Normal file
12
Data/Repositories/FeedRepository.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using LiveGameFeed.Data.Abstract;
|
||||||
|
using LiveGameFeed.Models;
|
||||||
|
|
||||||
|
namespace LiveGameFeed.Data.Repositories
|
||||||
|
{
|
||||||
|
public class FeedRepository : EntityBaseRepository<Feed>, IFeedRepository
|
||||||
|
{
|
||||||
|
public FeedRepository(LiveGameContext context)
|
||||||
|
: base(context)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Data/Repositories/MatchRepository.cs
Normal file
12
Data/Repositories/MatchRepository.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using LiveGameFeed.Data.Abstract;
|
||||||
|
using LiveGameFeed.Models;
|
||||||
|
|
||||||
|
namespace LiveGameFeed.Data.Repositories
|
||||||
|
{
|
||||||
|
public class MatchRepository : EntityBaseRepository<Match>, IMatchRepository
|
||||||
|
{
|
||||||
|
public MatchRepository(LiveGameContext context)
|
||||||
|
: base(context)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Models/Feed.cs
Normal file
13
Models/Feed.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LiveGameFeed.Models
|
||||||
|
{
|
||||||
|
public class Feed : IEntityBase
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public int MatchId { get; set; }
|
||||||
|
public Match Match { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Models/IEntityBase.cs
Normal file
12
Models/IEntityBase.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace LiveGameFeed.Models
|
||||||
|
{
|
||||||
|
public interface IEntityBase
|
||||||
|
{
|
||||||
|
int Id { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Models/Match.cs
Normal file
22
Models/Match.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace LiveGameFeed.Models
|
||||||
|
{
|
||||||
|
public class Match : IEntityBase
|
||||||
|
{
|
||||||
|
public Match()
|
||||||
|
{
|
||||||
|
Feeds = new List<Feed>();
|
||||||
|
}
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Host { get; set; }
|
||||||
|
public string Guest { get; set; }
|
||||||
|
public int HostScore { get; set; }
|
||||||
|
public int GuestScore { get; set; }
|
||||||
|
public DateTime MatchDate { get; set; }
|
||||||
|
public string League { get; set; }
|
||||||
|
|
||||||
|
public ICollection<Feed> Feeds { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Startup.cs
12
Startup.cs
@@ -2,8 +2,12 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using LiveGameFeed.Data;
|
||||||
|
using LiveGameFeed.Data.Repositories;
|
||||||
|
using LiveGameFeed.Data.Abstract;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -27,6 +31,12 @@ namespace LiveGameFeed
|
|||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
services.AddDbContext<LiveGameContext>(options => options.UseInMemoryDatabase());
|
||||||
|
|
||||||
|
// Repositories
|
||||||
|
services.AddScoped<IMatchRepository, MatchRepository>();
|
||||||
|
services.AddScoped<IFeedRepository, FeedRepository>();
|
||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
|
|
||||||
@@ -61,6 +71,8 @@ namespace LiveGameFeed
|
|||||||
template: "{controller=Home}/{action=Index}/{id?}");
|
template: "{controller=Home}/{action=Index}/{id?}");
|
||||||
});
|
});
|
||||||
app.UseSignalR();
|
app.UseSignalR();
|
||||||
|
|
||||||
|
LiveGameDbInitializer.Initialize(app.ApplicationServices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { FeedService, ConnectionState } from './shared/feed.service'
|
import { FeedService } from './shared/feed.service';
|
||||||
|
import { ConnectionState } from './shared/interfaces';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-app',
|
selector: 'my-app',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { FeedService, ConnectionState } from '../shared/feed.service';
|
import { FeedService } from '../shared/feed.service';
|
||||||
|
import { ConnectionState } from '../shared/interfaces';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'home',
|
selector: 'home',
|
||||||
|
|||||||
@@ -5,25 +5,7 @@ import 'rxjs/add/operator/toPromise';
|
|||||||
import { Observable } from "rxjs/Observable";
|
import { Observable } from "rxjs/Observable";
|
||||||
import { Subject } from "rxjs/Subject";
|
import { Subject } from "rxjs/Subject";
|
||||||
|
|
||||||
interface FeedSignalR extends SignalR {
|
import { FeedSignalR, FeedProxy, FeedClient, ConnectionState } from './interfaces';
|
||||||
broadcaster: FeedProxy
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FeedProxy {
|
|
||||||
client: FeedClient
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FeedClient {
|
|
||||||
userConnected: (user: any) => void;
|
|
||||||
userDisconnected: (id: string) => void;
|
|
||||||
messageReceived: (message: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ConnectionState {
|
|
||||||
Connected = 1,
|
|
||||||
Disconnected = 2,
|
|
||||||
Error = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FeedService {
|
export class FeedService {
|
||||||
|
|||||||
20
app/shared/interfaces.ts
Normal file
20
app/shared/interfaces.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/* SignalR related interfaces */
|
||||||
|
export interface FeedSignalR extends SignalR {
|
||||||
|
broadcaster: FeedProxy
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FeedProxy {
|
||||||
|
client: FeedClient
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FeedClient {
|
||||||
|
userConnected: (user: any) => void;
|
||||||
|
userDisconnected: (id: string) => void;
|
||||||
|
messageReceived: (message: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ConnectionState {
|
||||||
|
Connected = 1,
|
||||||
|
Disconnected = 2,
|
||||||
|
Error = 3
|
||||||
|
}
|
||||||
@@ -11,6 +11,9 @@
|
|||||||
"Microsoft.AspNetCore.SignalR.Server": "0.2.0-*",
|
"Microsoft.AspNetCore.SignalR.Server": "0.2.0-*",
|
||||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0-*",
|
"Microsoft.AspNetCore.StaticFiles": "1.1.0-*",
|
||||||
"Microsoft.AspNetCore.WebSockets": "0.2.0-*",
|
"Microsoft.AspNetCore.WebSockets": "0.2.0-*",
|
||||||
|
"Microsoft.EntityFrameworkCore": "1.0.1",
|
||||||
|
"Microsoft.EntityFrameworkCore.InMemory": "1.0.0",
|
||||||
|
"Microsoft.EntityFrameworkCore.Relational": "1.0.1",
|
||||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||||
"Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
|
"Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
|
||||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user