Moq setting up variables inside a method - c#

I have the following method that I am trying to test, but my variables are null even if I try to set them up.
public void Cancel(Guid id)
{
var order = _orderRepository.Find(o => o.Id == id); ** This never gets set, even with the setup below.**
if (order == null) return; ** Test Fails here. Returns and all assertions fails.**
order.Status = OrderStatus.Cancelled;
_orderRepository.Update(order);
}
[SetUp]
public void Setup()
{
_orderRepositoryMock = new Mock<IRepository<Order>>();
_accountServiceMock = new Mock<IAccountService>();
_orderService = new OrderService(_accountServiceMock.Object, _orderRepositoryMock.Object);
order = new Order()
{
Id = Guid.NewGuid(),
Customer= new ApplicationUser()
{
Id = Guid.NewGuid().ToString(),
Email = "test#test.com",
FirstName = "Tester",
LastName = "Test",
Address = "123 45 Ave",
City = "ABCVille",
PhoneNumber = "1-888-888-8888",
PostalCode = "T3J 0A4",
Province = "Super"
},
OrderAddons = new List<OrderAddon>(),
Total = 363.99m,
Status = OrderStatus.Created
};
}
[Test]
public void CancelShouldCallRepositoryWhenValid()
{
//var order ... (test data, in setUp)
var id = Guid.NewGuid();
order.Id = id;
// Repository Setup
_orderRepositoryMock.Setup(x => x.Find(o => o.Id == id)).Returns(order);
var wasOrderStatusUpdatedCorrectly = false;
_orderRepositoryMock.Setup(x => x.Update(order))
.Callback((Order o) =>
{
wasOrderStatusUpdatedCorrectly = o.Status == OrderStatus.Cancelled;
});
// Test Service
_orderService.Cancel(id);
// Test Assertions
_orderRepositoryMock.Verify(x => x.Find(o => o.Id == It.IsAny<Guid>()), Times.Once);
_orderRepositoryMock.Verify(x => x.Update(order), Times.Once);
}
Is there anyway to test "var order" ? I tried SetupGet as well and didn't seem to work, Moq is new to me so forgive me in advance if this is something simple and easy.

I think the problem is the Expression that the repository's Find method expects. Try this instead:
_orderRepositoryMock
.Setup(x => x.Find(It.IsAny<Expression<Func<Order, bool>>>()))
.Returns(order);
I'm just guessing at the type parameter for the Expression<>, but hopefully that helps.

Related

Push multiple objects with dynamic data into a DTO and return it

So I'm trying to use a DTO to reshape and return data, it's not working because I'm trying to push in an array of objects (as an IQueryable - which I don't think works) into the DTO, I'm also trying to push in dynamic data into one of the properties, as seen below in the 'hasCurrentUserLiked' property. I need to figure out How to change the objects from IQueryable, into actual objects so they can all be pushed into the DTO and the dynamic data can be worked out.
This is the code
public async Task<PagedList<UserPhoto>> GetSpecificFeed(UserParams userParams)
{
var user = _context.Users.FirstOrDefault(x => x.Username == userParams.u);
var userId = user.Id;
var photos = _context.UserPhotos;
var followerIds = _context.Follows.Where(x => x.FollowerId == userId).Select(x => x.FollowingId).ToList();
var feeds = _context.UserPhotos.Where(x => followerIds.Contains(x.UserId)).OrderByDescending(x => x.DateAdded);
// this doesn't work because 'feeds' is an IQueryable, not an object
var like = await hasCurrentUserLiked(user.Id, feeds.id);
// this has the same problem as above
var feedsToReturn = new FeedsForReturnDto
{
Id = feeds.Id,
PhotoUrl = feeds.photoUrl,
Username = feeds.Username,
Description = feeds.Description,
DateAdded = feeds.DateAdded,
IsImage = feeds.IsImage,
hasCurrentUserLiked = like,
Likes = feeds.Likes
}
return await PagedList<UserPhoto>.CreateAsync(feedsToReturn, userParams.PageNumber, userParams.PageSize);
}
I thought that I might be able to get each image.id in a similar way the 'followerIds' are worked out but I couldn't figure out how to get this to work
[EDIT]
As per Enas Osamas answer, I've changed the code to this and I've debugged it, feedsToReturn has the correct info, so it is doing what its supposed to do. The problem I'm having now is that I'm unable to return it as it can't convert the IEnumerable to an IQueryable. I tried adding an explicit cast but that didn't work, I also tried removing the PagedList, and replacing the type to but this didn't work. My is an IQueryable which might be the problem, I tried changing that to an IEnumerable but this would mess up the code in other places.
This is my new code (still returning 'feeds' instead of 'feedsToReturn', will change when it works)
public async Task<PagedList<UserPhoto>> GetSpecificFeed(UserParams userParams)
{
var user = _context.Users.FirstOrDefault(x => x.Username == userParams.u);
var userId = user.Id;
var photos = _context.UserPhotos;
var followerIds = _context.Follows.Where(x => x.FollowerId == userId).Select(x => x.FollowingId).ToList();
var feeds = _context.UserPhotos.Where(x => followerIds.Contains(x.UserId)).OrderByDescending(x => x.DateAdded);
var feedToReturn = feeds.AsEnumerable().Select(feed => new FeedsForReturnDto
{
Id = feed.Id,
PhotoUrl = feed.photoUrl,
Username = feed.Username,
Description = feed.Description,
DateAdded = feed.DateAdded,
IsImage = feed.IsImage,
hasCurrentUserLiked = hasCurrentUserLiked(user.Id, feed.Id),
Likes = feed.Likes
});
return await PagedList<UserPhoto>.CreateAsync(feeds, userParams.PageNumber, userParams.PageSize);
}
I also tried changing some of the types around and this is what I came up with. The problem here is this:
'System.Collections.Generic.IEnumerable<cartalk.api.Dtos.feeds.FeedsForReturnDto>' to 'System.Linq.IQueryable<System.Collections.IEnumerable>'
and this problem is with the 'feedsToReturn' in the last line
public async Task<PagedList<IEnumerable>> GetSpecificFeed(UserParams userParams)
{
var user = _context.Users.FirstOrDefault(x => x.Username == userParams.u);
var userId = user.Id;
var photos = _context.UserPhotos;
var followerIds = _context.Follows.Where(x => x.FollowerId == userId).Select(x => x.FollowingId).ToList();
var feeds = _context.UserPhotos.Where(x => followerIds.Contains(x.UserId)).OrderByDescending(x => x.DateAdded);
var feedToReturn = feeds.AsEnumerable().Select(feed => new FeedsForReturnDto
{
Id = feed.Id,
PhotoUrl = feed.photoUrl,
Username = feed.Username,
Description = feed.Description,
DateAdded = feed.DateAdded,
IsImage = feed.IsImage,
hasCurrentUserLiked = hasCurrentUserLiked(user.Id, feed.Id),
Likes = feed.Likes
});
return await PagedList<IEnumerable>.CreateAsync(feedToReturn, userParams.PageNumber, userParams.PageSize);
}
PagedList code
public static async Task<PagedList<T>> CreateAsync(IQueryable<T> source,
int pageNumber, int pageSize)
{
var count = await source.CountAsync();
var items = await source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToListAsync();
return new PagedList<T>(items, count, pageNumber, pageSize);
}
[EDIT]
This is the hasCurrentUserLiked function, it works here
public bool checkCurrentUserLiked(int currentUserId, int imageId)
{
var doesCurrentUserLike = _context.PhotoLikes.Where(x => x.LikerId == currentUserId && x.ImageId == imageId);
var value = true;
if (doesCurrentUserLike == null)
{
value = false;
}
else
{
value = true;
}
return value;
}
You can try something like
feeds.AsEnumerable().Select(feed => new FeedsForReturnDto
{
Id = feed.Id,
PhotoUrl = feed.photoUrl,
Username = feed.Username,
Description = feed.Description,
DateAdded = feed.DateAdded,
IsImage = feed.IsImage,
hasCurrentUserLiked = hasCurrentUserLiked(user.Id, feed.id),
Likes = feed.Likes
});
This would return an IEnumerable containing all the feeds mapped to your DTO after being enumerated to avoid performing operations against the database
[EDIT]
you can maybe do a left join with the _context.PhotoLikes.
Like this
feeds.GroupJoin(_context.PhotoLikes,
f => new { Id = f.Id, UserId = user.Id },
p => new { Id = p.ImageId, UserId = p.LikerId },
(f, p) => new { feed = f, photoLike = p })
.SelectMany(f => f.photoLike.DefaultIfEmpty(),
(f, p) => new FeedsForReturnDto
{
Id = f.feed.Id,
PhotoUrl = f.feed.photoUrl,
Username = f.feed.Username,
Description = f.feed.Description,
DateAdded = f.feed.DateAdded,
IsImage = f.feed.IsImage,
hasCurrentUserLiked = p != null,
Likes = feed.Likes
});
Just note that in this part
f => new { Id = f.Id, UserId = user.Id },
p => new { Id = p.ImageId, UserId = p.LikerId },
the datatypes of properties in both objects must match or it won't compile

Mocking 2 or more DBContext calls to the same entity fails

I've got an MVC ASP.Net app using Entity Framework v6.0 with an Employee's table.
We're using a Code First approach with the standard Create (CRUD) method that has a EF lookup for existing employee's and also an EF lookup for employee CreatedBy/ModifiedBy fields. Trying to create mocks for both (EF object stubs) fails.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "EmployeeID,TeamID,EmployeeADID,FirstName,MiddleName,LastName,EmailAddress,IsAdministrator,IsDeleted")] Employee employee)
{
if (ModelState.IsValid)
{
//Only unique employee IDs
var existingEmployee = db.Employees.FirstOrDefault(o => o.EmployeeADID == employee.EmployeeADID);
if(existingEmployee != null)
{
ViewBag.Error = "Employee ID must be unique, this employee (" + existingEmployee.FullName + ") already exists in the system.";
ViewBag.TeamID = new SelectList(db.Teams, "TeamID", "Name", employee.TeamID);
return View(existingEmployee);
}
SetAuditFields(employee);
db.Employees.Add(employee);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.TeamID = new SelectList(db.Teams, "TeamID", "Name", employee.TeamID);
return View(employee);
}
The problem is the SetAuditFields call and I need to mock db.Employees.AsNoTracking AsNoTracking for the Edit operation.
private void SetAuditFields(Employee employee, bool onlyModified = false)
{
char sep = '\\';
string pID = User.Identity.Name.Split(sep)[1].ToUpper();
var users = db.Employees.AsNoTracking().Where(c => c.EmployeeADID == pID || c.EmployeeID == employee.EmployeeID).ToList();
var currentUser = users.FirstOrDefault(u => u.EmployeeADID == pID);
if (onlyModified)
{
//Notice the AsNoTracking, when you set the db.Entry(object).State = EntityState.Modified; this query wont return anything as its in Modified Mode.
//var originalEmployee = db.Employees.AsNoTracking().FirstOrDefault(o => o.EmployeeID == employee.EmployeeID);
var originalEmployee = users.FirstOrDefault(o => o.EmployeeID == employee.EmployeeID);
employee.CreatedByID = originalEmployee.CreatedByID;
employee.CreatedDate = originalEmployee.CreatedDate;
employee.ModifiedByID = currentUser.EmployeeID;
employee.ModifiedDate = DateTime.Now;
}
else
{
employee.CreatedByID = currentUser.EmployeeID;
employee.CreatedDate = DateTime.Now;
employee.ModifiedByID = currentUser.EmployeeID;
employee.ModifiedDate = DateTime.Now;
}
}
So how do I mock db.Employees.AsNoTracking after initially mocking db.Employees?
The THESE TWO LINES COMMENTED OUT in the code below don't work and fail with:
"The member 'IQueryable.Provider' has not been implemented on type 'DbSet1Proxy' which inherits from 'DbSet1'
I also tried the mockContext.SetupSequence but I need to interchange between with AsNoTracking on and off. Surely there must be something I'm missing?
[TestMethod()]
public void Create_Submit_Test()
{
// Arrange
var employeeDoesntExist = new Employee { EmployeeID = 0, FirstName = "DoesntExist" };
var employeeAdmin = new Employee { EmployeeID=140, FirstName = "Bern", MiddleName = "", LastName = "O", EmployeeADID = "123", EmailAddress = "Bernard.O#a.com", TeamID = 1, IsDeleted = false, IsAdministrator = true };
var employeeNew = new Employee { FirstName = "Jez", MiddleName = "", LastName = "T", EmployeeADID = "321", EmailAddress = "Jeremy.Thompson#a.com", TeamID = 1, IsDeleted = false, IsAdministrator = true };
var mockContext = new Mock<ICTEntities>();
var employeeEmptyMock = base.GetQueryableMockDbSet(employeeDoesntExist);
var employeeAdminMock = base.GetQueryableMockDbSet(employeeAdmin);
//THESE TWO LINES COMMENTED OUT
//mockContext.Setup(m => m.Employees).Returns(employeeEmptyMock);
//mockContext.Setup(m => m.Employees.AsNoTracking()).Returns(employeeAdminMock);
mockContext.SetupSequence(x => x.Employees.AsNoTracking())
.Returns(employeeEmptyMock)
.Returns(employeeAdminMock);
//I dont want to save it to the Database, otherwise next time we run this the object will already exist, so I mock the call
mockContext.Setup(d => d.SaveChanges()).Returns(1);
var controller = new EmployeesController(mockContext.Object);
controller.ControllerContext = base.MockAccess().Object;
// Act
RedirectToRouteResult result = controller.Create(employeeNew) as RedirectToRouteResult;
// Assert
Assert.IsNotNull(result);
Assert.AreEqual("Index", result.RouteValues["Action"]);
}
Here is the GetQueryableMockDbSet method:
protected DbSet<T> GetQueryableMockDbSet<T>(params T[] sourceList) where T : class
{
var queryable = sourceList.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
return dbSet.Object;
}
I ended up creating a chain of mocks using a counter as per https://stackoverflow.com/a/14368486/495455
int callCounter = 1;
mockContext.Setup(m => m.Employees)
.Returns(() =>
{
if (callCounter == 1)
{
callCounter++;
return employeeToEditMockCU;
}
else
{
return employeeMockCU;
}
});
Mocking using a SetupSequence doesn't work for me after the first mock. The db.Employee becomes null after the first call. So I dont use a SetupSequence:
mockContext.SetupSequence(x => x.Employees)
.Returns(employeeToEditMockCU)
.Returns(employeeMockCU);
Also to get around the AsNoTracking() I ended up fetching the record to update and saving it without using EntityState.Modified:
EF Update using EntityState.Modified
How to update record using Entity Framework 6?

C# query MongoDB using GroupBy

I have a mongodb object as following:
public class Form
{
public string FormId { get; set; }
public boolean Status { get; set; } //Published or Draft
public int Version { get; set; } //The version of the same forms.
}
For the same FormId, there could be different version number and different Status. Some example data such as:
{
"FormId":"1",
"Status":true,
"Version":1
};
{
"FormId":"1",
"Status":true,
"Version":2
};
{
"FormId":"2",
"Status":true,
"Version":1
};
{
"FormId":"2",
"Status":true,
"Version":2
};
{
"FormId":"2",
"Status":false,
"Version":1
}
Now I want to get a list of forms that for the same FormId, the Status is true and the version number is the largest. So the query result should be:
{
"FormId":"1",
"Status":true,
"Version":2
}
and
{
"FormId":"2",
"Status":true,
"Version":2
}
I tried to write the query in C# using Lambda expression:
this.AsQueryable<Form>().Where(p=>p.Status == true)
.GroupBy(item=>item.FormId)
.Select(t=>t.OrderByDescending(c => c.Version).FirstOrDefault()).ToList();
But I got error:
Additional information: FirstOrDefault of type System.Linq.Enumerable is not supported in the expression tree {document}.OrderByDescending(c => c.Version).FirstOrDefault().
Does anyone know what is wrong with my code? By the way, how can I know what is supported or not supported in the expression tree?
I found out that if I write the query as following it works, but I believe this is not a good approach.
return this.AsQueryable<FormTemplateEntity>().Where(p=>p.Status == true).ToList()
.GroupBy(item => item.FormId).ToList()
.Select(t => t.OrderByDescending(c => c.Version).FirstOrDefault()).ToList();
Updated my syntax and tested to be working.
this.Where(x => x.Status)
.GroupBy(item => new { item.FormId, item.Status })
.Select(x =>
new Form
{
FormId = x.First().FormId,
Status = x.First().Status,
Version = x.OrderByDescending(c => c.Version).First().Version
}
).ToList();
Output:
[{"FormId":"1","Status":true,"Version":2},{"FormId":"2","Status":true,"Version":2}]
Actual Code used to test:
var _json =
"[{ \"FormId\":\"1\", \"Status\":true, \"Version\":1},{ \"FormId\":\"1\", \"Status\":true, \"Version\":2},{ \"FormId\":\"2\", \"Status\":true, \"Version\":1},{ \"FormId\":\"2\", \"Status\":true, \"Version\":2},{ \"FormId\":\"2\", \"Status\":false, \"Version\":1}]";
var js = new JavaScriptSerializer();
List<Form> resultList = js.Deserialize<List<Form>>(_json);
var groupedResult = resultList.Where(x => x.Status).GroupBy(item => new { item.FormId, item.Status })
.Select(x =>
new Form
{
FormId = x.First().FormId,
Status = x.First().Status,
Version = x.OrderByDescending(c => c.Version).First().Version
}
).ToList();
var output = js.Serialize(groupedResult);
public List<Form> GetFromDetails()
{
var DB = new Database();
var collection = DB.GetCollection<Form>();
var query = new QueryBuilder<Form>();
var queryLst = new List<IMongoQuery>();
// {
// "FormId":"1",
// "Status":true,
// "Version":1
//};
//{
// "FormId":"1",
// "Status":true,
// "Version":2
//};
List<Form> finalResult = new List<Form>();
finalResult = collection.FindAll().Where(x => x.Status == true).ToList(); // pasing id 1
// {
// "FormId":"1",
// "Status":true,
// "Version":1
//};
//{
// "FormId":"1",
// "Status":true,
// "Version":2
//};
var finalResults = finalResult.Select(n => new Form
{
FormId = n.FormId,
Status = n.Status,
Version = finalResult.OrderByDescending(v => v.Version).First().Version
});
// {
// "FormId":"1",
// "Status":true,
// "Version":2
//};
//{
// "FormId":"1",
// "Status":true,
// "Version":2
//};
DB.Dispose();
return finalResult;
}
Above Method will help and i'm done because i myself made a demo its working
It didn't work for me, but I could make it by using Sort before Group.
return _context.Products
.Aggregate()
.Sort(Builders<Product>.Sort.Descending("InsertedDate"))
.Group(x => x.Code, g => new {Code = g.Key, LastInsertedDate = g.First().InsertedDate })
.ToList();

How do I get this mock to work?

I need to make changes to a legacy class with no tests so I have started by writing a test, however the mocking (using Moq) isn't working properly.
This my test
[Test]
public void CorrectlyCopiesToLightningWhenNoLocationsExist()
{
// arrange
long orgId = Id64.NewId();
var data = LightningMapLocationsHelperTestData.ForNormalCopy(orgId);
var organisation = new Group
{
GroupId = orgId,
Name = "Test Organisation",
Type = GroupType.OrganisationGroup
};
var groupRepo = new Mock<IGroupRepository>();
groupRepo.Setup(r => r.GetGroup(orgId)).Returns(organisation);
var orgRepo = Mock.Of<IOrganisationRepository>(o => o.LightningLocationsEnabledFor(orgId));
var mapLocationRepo = new Mock<IMapLocationRepository>();
mapLocationRepo.Setup(r => r.OrganisationRepository).Returns(orgRepo);
mapLocationRepo
.Setup(r => r.GetMapLocationsByGroupIds(orgId, It.IsAny<IEnumerable<long>>(), true, true))
.Returns(data.InitialDatabaseLocations);
var lightningMapLocationRepo = new Mock<ILightningMapLocationRepository>();
lightningMapLocationRepo
.Setup(r => r.LocationsById(orgId, data.InitialLightningLocations.Select(l => l.LocationId)))
.Returns(data.InitialLightningLocations);
lightningMapLocationRepo
.Setup(r => r.AddLocations(It.IsAny<List<Location>>()))
.Callback((List<Location> locations) => data.InitialLightningLocations.AddRange(locations));
var infoMessages = new List<string>();
var errorMessages = new List<string>();
var helper = new LightningMapLocationsHelper(
(string s, object[] args) => infoMessages.Add(string.Format(s, args)),
(string s, object[] args) => errorMessages.Add(string.Format(s, args)));
List<CopyFailure> copyFailures;
// act
bool success = helper.CopyLocationsForOrganisation(orgId, 10, out copyFailures);
// assert
success.ShouldBeTrue();
(errorMessages?.Count ?? 0).ShouldBe(0);
data.InitialLightningLocations.Count.ShouldBe(data.ExpectedLightningLocations.Count);
}
Inside LightningMapLocationsHelper is the following method
private Group GetValidOrganisationGroup(long groupId)
{
var organisation = (new GroupRepository()).GetGroup(groupId);
if (organisation != null && organisation.Type == GroupType.OrganisationGroup) return organisation;
LogErrorMessage("Invalid groupId: {0}. Ignoring...", groupId);
return null;
}
that when called is using an actual instance of GroupRepository rather than the groupRepo mock set up in the test, thus causing the test to fail. As GroupRepository implements IGroupRepository I expected this to work.
public class GroupRepository : IGroupRepository {…}
Perhaps I am misunderstanding how mocking works. Can someone offer some insight to help me understand why this doesn't work, and how I can fix it? Do I have to pass the mocked classes in?

Using EF to return specific formatted JSON from ASP.NET MVC

I have a model like below where PermissionGroup has 1-Many relationship with Permission and Permission and Roles have Many-Many relationship.
PermissionGroup 1-----* Permission *--------* Role
I have to be able to return JSON in the following format:
PermissionGroupId : 1,
PermissionGroupName : "Market",
Permissions : [
{PermissionId : 1, PermissionName : "Create"},
{PermissionId : 2, PermissionName : "Update"}
]
That will be asked for a specific RoleId.
Problem:
Since, PermissionGroup has no relation directly with Role so I cannot do a Where linq query. I could do the following but it is not returning desired result like above.
public JsonResult GetRolePermission(int roleid)
{
var list = con.PermissionGroups.Select(pg => new
{
PermissionGroupId = pg.PermissionGroupId,
PermissionGroupName = pg.PermissionGroupName,
Permissions = pg.Permissons.Select(pe => new
{
PermissionId = pe.PermissionId,
PermissionName = pe.PermissionName
})
})//Maybe do the where query here somehow like where(f => f.RoleId == roleid);
return Json(list);
}
Any suggestion is appreciated.
You can use Any method in Where? Like this:
var list = con.PermissionGroups
.Where(pg => pg.Permissons.Any(p => p.Roles.Any(r => r.RoleId == roleId)))
.Select(pg => new
{
PermissionGroupId = pg.PermissionGroupId,
PermissionGroupName = pg.PermissionGroupName,
Permissions = pg.Permissons.Select(pe => new
{
PermissionId = pe.PermissionId,
PermissionName = pe.PermissionName
})
});
I found a way to do this but highly doubt that it is efficient.
var getPermissionsForRole = context.Roles.Where(roleid => roleid.RoleId == 1).Select(p => p.Permissions).ToList();
var getAllPermissionGroup = context.PermissionGroups.ToList();
List<PermissionGroup> jsonPg = new List<PermissionGroup>();
foreach (var pg in getAllPermissionGroup)
{
PermissionGroup newPg = new PermissionGroup();
newPg.PermissionGroupId = pg.PermissionGroupId;
newPg.PermissionGroupName = pg.PermissionGroupName;
newPg.Permissons = new List<Permission>();
foreach (var pers in getPermissionsForRole[0])
{
if (pers.PermissionGroup.PermissionGroupId == pg.PermissionGroupId)
{
Permission newPe = new Permission();
newPe.PermissionId = pers.PermissionId;
newPe.PermissionName = pers.PermissionName;
newPg.Permissons.Add(newPe);
}
}
if (newPg.Permissons.Count > 0)
{
jsonPg.Add(newPg);
}
}
var json = JsonConvert.SerializeObject(jsonPg);
Still open to better code.

Categories