Blazor Parameter Object or child API call or Virualization? - c#

I am working on a project that includes a list of Help Articles.
Clicking on an Article in the list opens the Article.
OnInitializedAsync() calls to the API for the Article.include(Comments).theninclude(Replies).
I have a CommentList component that builds the comment list using instances of Comment component
Each Comment has a ReplyList component that builds a reply list using instances of Reply component
The page is built:
Article API Call including Comments then Replies
CommentList [Parameter] public <ArticleDto> Article
Comment instances [Parameter] public <CommentDto> Comment
ReplyList [Parameter] public <ReplyDto> Reply
Reply instances [Parameter] public <ReplyDto> Reply
The page is slow to render with a lot of foreach and if checks so I'm left wondering if my approach is a bit immature?
If you've faced this dilemma, I'd love to hear what your approach was.
I'm considering having each list component make its own API call but I was hoping to avoid multiple calls to build a single page. Virtualization seems like a good candidate perhaps?

Related

blazor- create subpage path extension like "~/product/{itemId:int}/edit"

The title need to be changed; Because I don't know how to describe my problem. Lets say we have this pages:
localhost:5000/counter
localhost:5000/products/{itemId:int}
localhost:5000/employee/{userId:int}
The idea is to create a universal subpage "/Edit" like:
localhost:5000/counter/Edit
localhost:5000/products/{itemId:int}/Edit
localhost:5000/employee/{userId:int}/Edit
The page should lode as it was but with places to edit that specific (item, user or the parameter) in the page.
Another example could be "/Report"
The main goal is that the page base url do not change! => This is not okey
localhost:5000/Edit/user/{userId:int}.
The main problem that I'm getting is that I can't add parameters before the subpage-Extension. Repeated code to check the url in every page will be pain.
I'm making my website like File-Explorer, the path is like this:
localhost:5000/Folder/{path:string}
// will show => list of folders and files
//
// or => a file => ImgeFile-view component
// => PdfFile-view component
// => wordFile-view component
// => video.....
Each component have it's own properties even the folder. so if i'm logged-in as admin and i add /edit to the end of any url i need to be able to edit the content and send it back to the DB.
Next step will be to change the (html or blazor) tags to input with the tags id and interface's.
Please comment with your ideas or objections.
exploring how to make a custom router sounds fun, do you have anything that will help me start with it?
The .Net Core Router code is here in the aspnetcore Github repository - https://github.com/dotnet/aspnetcore/blob/main/src/Components/Components/src/Routing/Router.cs.
It's not that easy to lift "as is" because a lot of the support classes are internal assembly classes. You'll have to copy and refactor a lot of classes to get it running.
I've already written a custom router, so done the work. Your welcome to lift the code. You can find everything in a Github repo here - https://github.com/ShaunCurtis/Blazr.Demo.EditForm.
The actual library detail is here - https://github.com/ShaunCurtis/Blazr.Demo.EditForm/tree/master/Blazr.NavigationLocker
Perhaps I'm misunderstanding the question but you can have multiple paths for one page. On the Edit page include all three paths;
#page "/counter/Edit"
#page "/products/{itemId:int}/Edit"
#page "/employee/{userId:int}/Edit"
(Edit Page Markup)
#code {
[Parameter]
public int itemId { get; set; }
[Parameter]
public int userId { get; set; }
}
You don't need to check the url in every request. It's a bit yucky but if itemId and userId are both 0 than you know your in counter. If itemId is greater than 0 you know your in products and if userId is greater than 0 you know your in employee.

MVC / ViewModel - Trouble with Best Practices in ASP.Net Core 3.1+

I'm relatively new to web development in my current role and we have an MVC SPA type application I'm developing with my team. I can't really share any code directly as it's all the property of my company, so generally:
We're currently working to make a wizard that will collect several points of data and combine it all into the backend's SQL Stored Procs for inserting into tables. To start we've built a viewmodel that injects in and displays the possible options for various fields / drop downs. As choices are made in the drop downs it draws in new layers of the wizard.
To keep track of everything selected, I feel like our current strategy might be suboptimal - or more complex than needed.
When the View is interacted with, we're serializing the #Model into json, pushing it into the controller along with any data gathered from the user, de-serializing it into the ViewModel type, and sending it back in to the new partial view - storing any modifications from that action.
This keeps track of the changes as the user works through the wizard and allows us to redraw the primary div/page space to get new information as the context of what we're asking for changes.
I've seen websites do this with Forms or other things like modal pop ups, but as this is a multi step conditional wizard I chose against using that pathway as the views quickly became a mess of conditional razor checks and in page updates.
I know enough to know I'm not sure what best practices are in web development and I'm finding it difficult to extrapolate from various tutorials around the web into the complexity of this particular project.
I can give a generified example of code below, but hopefully the explanation above will trigger someone's brain to help short cut me to a cleaner way to do this.
public class XController : Controller
{
...
public XController(XRepository xRepository, IViewModelFactory viewModelFactory, Input input)
{
_xRepository = xRepository;
_viewModelFactory = viewModelFactory;
_input = input;
}
public IActionResult XIndex()
{
return PartialView(); //Draws an add/edit/delete set of buttons to begin the wizard. Assume the Add button is clicked leading to the next method.
}
public IActionResult DisplayAddJob()
{
//get list of task and connection types so user can select
_taskTypes = _xRepository.GetTaskTypes().ToList();
_connectionTypes = _xRepository.GetConnectionTypes().ToList();
_queryTypes = _xRepository.GetQueryTypes().ToList();
//build and return viewmodel so u can bind it to AddjobIndex dropdowns
XViewModel xvm = _viewModelFactory.Build(User.Identity, _taskTypes, _connectionTypes,_queryTypes, "Miscellaneous", _input.Test);=
return PartialView(xvm); //The initial view model creation / draw happens here
}
[ActionName("JobQueryWithPriorData")]
public IActionResult JobQuery(string vConnection, string vmJson)
{
xConnection vc = JsonConvert.DeserializeObject<xConnection>();
xViewModel xvm = JsonConvert.DeserializeObject<xViewModel>(vmJson);
xvm.SelectedConnectionId = (int)vc.ConnectionId; //we equip the view model with data that changed in the page interaction
return PartialView("~/Views/Miscellaneous/X/JobQuery.cshtml", xvm); //redraw the view in the main content pane with the updates.
}
...
}
This pattern exists all across the controller. An example of the .cshtml code #razor / javascript calls into the Controller are as follows:
Razor:
<td class="td-main-table" valign="middle">
<button type="button" class="y" onclick="SelectButtonClicked('#JsonConvert.SerializeObject(Model.ConnectionList.Where(x=>x.ConnectionId == ct.ConnectionId))','#JsonConvert.SerializeObject(Model)')">
</button>
</td>
Javascript:
function SelectButtonClicked(vConnection, viewmodeljson)
{
var functionalUrl = '/X/QueryToTableWithPriorData'
$.ajax({
url: functionalUrl,
type: 'POST',
data: {
vConnection:vConnection,
vmJson:viewmodeljson
},
success:
function (response) {
$('#displayDataPartialView').html(response);
}
});
}
This methodology is working. We're slowly, over the life of the wizard, able to grab the users selections and keep track of them. I'm just curious if there is a better way to do this, as I'm certain if there is I'm not aware of where to hunt for it. I believe in the old days people would just store stuff in ViewData objects, but I didn't really start web dev until .net core 2.1.
My team and I have full creative control over this application, it's internal and something I built from the ground up specifically for our team to put internal tools into, it's fairly lightweight currently and I'm willing to modify it to have a better foundation going forward.
Would it be better to store the user selections in a table tied to the users session and just recall the data at the end of the wizard on submit?
Are forms more flexible than I think they are?
Should I use modal windows instead of redrawing the page every time as a step through this?
Edit:
After a few days of research, while I'm not sure I have the best practices by any stretch, I do believe what we're doing is adequate. I've learned more about client vs server-side rendering and I believe my post came from not quite understanding the two well enough.
I believe the functionality I was expecting was "client-side" functionality from a very server side framework: the ability to step through a wizard's various forms without losing the data as the client goes through. This can be achieved with javascript/angular/react/blazor manipulating the view without going back to the server with a post/get.
In the world where I'm using minimal javascript, the strategy I'm using to turn the model into json in order to attach more data to it on the server side and resend it to the client for further modification SEEMS appropriate.
I still am interested to see if anyone has a best practice, so I'll leave the question open for a bit longer to see if anyone has anything. It's possible I should add a more client side layer to the solution as currently my thought was to try and maximize how much I leveraged the C# portion of web development. It seems like that might be my overall issue here.
Additionally, I spent some time looking into ViewComponents at a the suggestion of a commenter, Xinran. They are neat and do perform similarly to the PartialView methodology I'm using. I like how they work, but they produce the same exact scenario. They are mostly server-side tools, and I still, in the end, run into exactly the scenario that makes me wonder if this is the best way to handle a wizard with multiple steps that evolves off the user's previous choices.

What is the most efficient method of detecting whether an object's content has changed and update the object? C#

The Problem
Often controller classes (MVC, MVVM, MVP) that manipulate views have access to a multitude of services. The purpose of one of these services is to update the controller classes with data that is pertinent to the controller.
Take this class for example:
public sealed class RestaurantInformation
{
public IEnumerable<Networking.Models.ServerModels.Restaurant> NearestRestaurants { get; internal set; }
public IEnumerable<Networking.Models.ServerModels.Restaurant> NewestRestaurants { get; internal set; }
public IEnumerable<Networking.Models.ServerModels.Category> Categories { get; internal set; }
}
Whenever the service receives updated information from the network regarding Categories, NewestRestaurants or NearestRestaurants, it packages all of the data into an object which has the class type RestaurantInformation and sends it to the controller class to pass to the view.
I decided to put my C grade in my art GCSE to good use and construct diagrams to aid your understanding of my problem. (Apologies for what you are about to see.)
As you can now see, the flow is as follows:
The view loads which in turn calls the RestaurantViewControl.
The RestaurantViewControl then calls the RestaurantService to retrieve the new categories from the API.
The API returns the new categories to the RestaurantService. (You can see here the restaurant service now has a list that contains B).
The RestaurantService then notify's the RestaurantViewControl using the class above with the new list of categories!
We must now update the list of categories in the RestaurantViewControl in the most efficient way possible with the new items.
I am currently clearing the categories list and then replacing all the values with the new list. The two things I want to know are:
What is the most efficient way to detect a change in the Categories List object?
What is the most efficient way to update the categories list which may still contain objects that are completely valid in that list.
Seems like you have a straight forward issue. You will have a services layer that calls when you show the restaurant list page.
So your collectionView/listView just displays the list of items in the view cell based on that data. One example https://almirvuk.blogspot.com/2019/07/lets-play-with-collectionview-layouts.html?m=1
Usually you’ll just do a check for changes on the first time you visit the page, pull to refresh, or if you set up caching-after a set time when the cache expires.

How do I implement subscriptions in GraphQL HotChocolate?

I am implementing HotChocolate as part of my ASP.NET API. I'm trying to add subscriptions to the chat portion on my app, however, the documentation on the HotChocolate site is not implemented yet. From what I can tell from other sites/frameworks, I can use the C# IObservable<Chat> as the return type for the subscription method.
Can anyone give me an example of a query method or point me towards another resource?
public async Task<IObservable<Message>> GetMessages(Guid chatId) {
var messages = ..Get chats;
return messages;
}
However, how does this work from a query standpoint? How do we trigger an event to update this?
Thanks.
Since the original documentation link became obsolete I am posting this new link that refers to our workshop project.
Chapter 7 shows how to do subscriptions in two variants.
https://github.com/ChilliCream/graphql-workshop/blob/master/docs/7-subscriptions.md
I hope that helps.

JSON response does not include the Nested content for a particular class

I am working with Kentico Cloud using KenticoCloud DeliveryClient.
The issue is that I am loading the data for NewsArticle which include BodyContent. The BodyContent has some InlineContentItemData supposed to be resolved by Resolvers.
I added PartnerList (item which includes several Partner items), Carousel (item which includes several ImageGridItem items) and some HTML text.
Here is the code to make the request:
var response = await Client.GetItemsAsync<NewsArticle>(
new EqualsFilter("system.type", "news_article"),
new OrderParameter("elements.date", SortOrder.Descending)
);
(it is to get a full list of articles, then we find out the desired article later. I know I can use Url Slug to retrieve the content, but I need the full list for other stuff)
The issue is that in the JSON response, there is Carousel and PartnerList item, both of them contain the items that I added from the CMS, but individual Carousel items (ImageGridItem) were not presented in the JSON, only Partner items.
Thanks
There could be multiple causes for this behavior. I assume you are using String based rendering of items in Rich text and code first approach so that you should have the ICodeFirstTypeProvider implementation defined and the resolvers as well.
Possible solutions:
Check that codename is correctly defined in your ICodeFirstTypeProvider implementation pointing to the Partner class.
You could also try to use the DepthParameter to force deeper loading of the data, but it is unlikely to solve the issue since the individual Carousel items are retrieved and they are in the same depth level.
If any of the assumptions are wrong, let me know. If you are willing to share the implementation of ICodeFirstTypeProvider and the implementations of IInlineContentItemsResolver for all the content types you are loading.
If you want to debug the SDK right from your project and find the cause on your own, there is a possibility to use the SourceLink.

Categories