Content Developer II at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
112797 stories
·
29 followers

Ghost in the IDE: Testing Replit’s AI Helper, Ghostwriter

1 Share
ghost

Recently, I’ve been taking a trip through tools that give the software developer hints, help, debugging advice or (in some cases) complete code snippets, boosted by what we are currently referring to as AI. My particular preference are hints given on the edit line, like Visual Studio already does and Copilot does even more of. Given that I like online sandboxes, and I’m looking at AI tools, there does seems one obvious tool I should investigate.

Replit is an already popular online IDE, where your projects are hosted on ‘Repls’ (the term REPL or read-eval-print loop is at the root of the name). Replit is a hosted solution, so collaboration is built in. Recently the company introduced its LLM service, Ghostwriter.

Unlike the general abilities of OpenAI, the Economist noticed that Replit was favouring using LLM models to focus just on development. They use the Databricks AI platform, which Nvidia are heavily invested in.

With no need to install anything, I went ahead and created an account with Google. I could, of course, have used GitHub for identity. Interestingly, Replit asks not just what your intended use is (personal, collaboration, etc.) but how much development you have done. The first thing I saw on the dashboard was a bounty board, which I did not expect to see. This just underlines that Replit is as much a community as a tool — so it has a handy internal marketplace.

But I’m here for the spook. I noted that I could pay for the services of Ghostwriter for $10, via “1000 Cycles”; that is, $10 buys a 1000 Cycles. At least Replit are not directly exposing their AI service costs, so if things change behind the scenes they can flex a little. And a virtual currency is transparent — it is, after all, what Fortnite does. Of course, Fortnite weighs prices carefully, so you find yourself needing just one more pack of V-bucks to buy that skin you want.

My aim is to use Ghostwriter on a ‘Repl’, so I’ll start with 1000 V-bucks Cycles and see how I do. I assume that a public Repl is free, which mirrors the Github pattern.

In a previous post, I used a small class to check out Copilot. What Copilot did was to complete my method based on its name (using common conventions) and using its understanding of the C# FlagsAttribute. All this does is indicate that an enumeration can be used as a bit field:

[Flags] public enum OccurrenceType {
   None = 0, 
   OccurrenceA = 1, 
   OccurrenceB = 2, 
   OccurrenceC = 4, 
   OccurrenceD = 8
} 
… 
private OccurrenceType occurrences { get; private set; } = OccurenceType.None


This technique is a compact way of storing events; it is also cheap to check whether the event has occurred. So I can represent OccurrenceA and OccurrenceC happening by bitwise ORing them together in a variable:

0000 (Nothing has happened)

OR

0001 (OccurrenceA happened)

OR

0100 (OccurrenceC happened)

-----

0101


And with the appropriate mask, we can quickly see whether, for example, OccurrenceC happened. This should be much more efficient than using a List.

So, I started a Repl and chose C#. After generating a C# template project, the little helper showed me around, but the screen comfortably follows the normal windowed display. Also, it invited me to try Ghostwriter:

Oddly, the Run button didn’t seem to work…at first. Then I noticed that my CPU maxed out, but it did eventually manage to print out “Hello World”. Hmm. I guess I can throw V-Bucks Cycles at it! (remember this is running on Replit’s infrastructural dime.)

Unfortunately, Ghostwriter started off unresponsive. This could have been because of network issues, or shyness. It didn’t tell me. I was getting responsiveness from the CPU cycles, but not Ghostwriter. While this is inevitable if you are offloading work to another service, the platform does need to do a little more work with health.

When the chat window finally responded, I was ready to go. Unfortunately, the Ghost was still not writing any hints in real time, but it was prepared to generate code in the edit window. So I asked it to create the SetOccurrences method. )

The first attempt didn’t work.

That is:

public void SetOccurrences(OccurrenceType occurrence)
{
    this.occurrences = occurrence;
}


This is wrong, but I didn’t really help much: this would have been better named “AddOccurrence”.

I rejected the hint and tried again, this time improving the name a little:

And this is correct. It is ORing the new occurrence in, not setting it directly. I still should have named it better, however.

I was less fortunate with the method to check whether an occurrence has, er, occurred. It took many rejections, but eventually, I got the right bitwise calculation answer:

This is the correct way to use the flags. It ANDs the storage variable with the occurrence to check for, treating it as a mask. Any non-zero result shows that the occurrence occurred. Again, maybe if I gave my ethereal partner a better clue in the name, perhaps HasOccurrence, it would have come to the right answer a little quicker.

I wanted to see if I could persuade it to use HasFlag, which is available in .NET 7. While it didn’t suggest this (had I looked in the project file, I would have seen that it wasn’t using this framework, so it never would suggest this) it did improve the suggestion a little:

public bool IsOccurrence(OccurrenceType occurrence) 
{ 
  return (occurrences & occurrence) == occurrence; 
}


…which is a nicer formulation. After adding some test execution lines to the main.cs file, and some console output, the project class worked as it should have:

Just one more thing; a debugging task. For the flags attribute to work, the enums must have the expected binary values. What would happen if I set OccurrenceD to 5? Ghostwriter didn’t appear to notice, and there did not appear to be a “debug” option. However, I asked it to “Explain the code” and got this excellent response while the error was in place:

This is absolutely correct, and even finds the bug during analysis — which is almost human.

Altogether, while Ghostwriter didn’t appear to perform very proactively for me, it was certainly quicker to set up than Visual Studio and Copilot. I suspect with more CPU available, and a fair wind, it could behave in a more forthright style. It takes time to get used to any pairing partner, whether corporeal or otherwise. And as Ghostwriter does its haunting closer to the Replit infrastructure, I suspect sightings will be more reliable and system health will be easier to show. In short, Replit is definitely advancing with the spirit of AI. It has much more than a ghost of a chance to succeed.

The post Ghost in the IDE: Testing Replit’s AI Helper, Ghostwriter appeared first on The New Stack.

Read the whole story
alvinashcraft
20 minutes ago
reply
West Grove, PA
Share this story
Delete

Secure Go APIs with Decentralized Identity Tokens, Part 3

1 Share

When used together in decentralized identity tokens, token expiry and claims can help establish a robust security posture for Go APIs, significantly reducing the risk of unauthorized access, session hijacking and potential security breaches.

Token expiry establishes an expiration time for each token issued. By setting a time limit, tokens become less susceptible to malicious exploitation even if they are leaked or compromised.

When combined with robust claims (a structured representation of user attributes and permissions), token expiry greatly minimizes the window of opportunity for attackers to misuse tokens and gain unauthorized access to sensitive resources. Token expiry compels users and clients to regularly request new tokens, promoting a continuous cycle of authentication and reducing the chances of impersonation.

By embedding relevant user attributes and permissions in claims, API endpoints can make informed access-control decisions. The presence of token expiry further fortifies this process, enhancing the principle of least privilege and minimizing potential damage in the event of a token leak.

An Overview of Token Expiry

Token expiry mechanism. Decentralized identity tokens typically include an expiration claim (exp) that specifies the date and time after which the token should no longer be considered valid. The expiry value is typically a timestamp in the form of the number of seconds or milliseconds since a specific reference point, such as the Unix epoch.

Token validation and expiry checks. Token validation logic should include checks to verify that the token has not expired. During token validation, the current time is compared against the token’s expiry time to determine if the token is still within its valid period.

In addition to the enhanced security offered by token expiry, Shorter token lifetimes help reduce the exposure of sensitive user information.

Token expiry durations can be configured based on the specific needs of an application. The chosen expiry duration should strike a balance between security requirements, user experience and the sensitivity of the data accessed by the tokens.

Shorter expiry durations increase security but may require more frequent re-authentication, while longer expiry durations provide convenience but increase the risk in the event of a token compromise.

Some decentralized identity frameworks use refresh tokens to maintain user sessions without frequent reauthentication. Refresh tokens have a longer lifespan and can be used to obtain new access tokens when they expire. This allows for a more seamless user experience while enforcing token expiry for security purposes.

If your decentralized identity framework supports refresh tokens, you can implement a mechanism to obtain new access tokens when they expire. This process involves exchanging a refresh token for a new access token without requiring user reauthentication. It allows for seamless continuation of user sessions while still enforcing token expiry.

How to Handle Token Expiration in Go APIs

Handling token expiration in Go APIs involves detecting expired tokens and prompting users to reauthenticate to obtain a fresh token. Here are the steps to follow:

1. Check the Token’s Expiry Time.

During the token validation process, compare the token’s expiry time (exp) with the current time. If the token has expired, you must take appropriate actions to prompt users to re-authenticate.

2. Return the Unauthorized Response.

When an expired token is detected, return an HTTP Unauthorized (401) response to the client. This informs the client that the token is no longer valid and that reauthentication is required.

3. Define an Authentication Challenge.

Along with the Unauthorized response, include an authentication challenge header, such as "WWW-Authenticate" or "Bearer realm", to instruct the client on how to initiate re-authentication. For example:

func YourHandler(w http.ResponseWriter, r *http.Request) {
  // Parse and validate the token


  if tokenExpired {
     w.Header().Set("WWW-Authenticate", `Bearer realm="Your Realm"`)
     http.Error(w, "Token expired, please reauthenticate.", http.StatusUnauthorized)
     return
  }


  // Token is valid, proceed with handling the request
  // ...
}

4. Handle the Reauthentication Flow.

The reauthentication flow depends on your specific authentication mechanism and requirements. You may redirect the user to a login page, display an interactive prompt, or initiate a new authentication request using an authentication protocol (such as OAuth 2.0). Customize the reauthentication flow based on your application’s design and user experience considerations.

5. Clear Invalid Tokens.

After notifying the client about the expired token, clear the invalid token from any client-side storage or caches to avoid further usage of the expired token.

6. Communicate Error Messages.

Provide clear error messages or responses to clients indicating that their token has expired and that they need to reauthenticate. This helps users understand the reason for the error and take appropriate actions.

7. Consider the User Experience.

Consider the impact on the user experience when handling token expiration. Strive for a seamless transition to the reauthentication flow, minimizing disruptions and providing clear instructions to the user on how to proceed.

How to Implement Token Revocation

Token revocation mechanisms are important for managing the validity and usage of tokens in a decentralized identity system. They allow you to revoke and invalidate tokens before their natural expiration, providing enhanced security and control over user access.

Token Revocation Methods

Token revocation can be achieved through several methods, each with its own advantages and considerations. The first approach is blacklisting, where a list of revoked tokens is maintained. During token validation, the API checks if the presented token is present in the blacklist. This method requires an efficient mechanism to store and query the revoked tokens.

Another method is token expiration. Instead of explicitly revoking tokens, tokens are given a short expiration duration. When a user needs to be revoked, their token is allowed to expire naturally. This approach reduces the need for tracking and managing a separate revocation list, but it may necessitate more frequent reauthentication to obtain a new token after the expiration.

Lastly, token versioning involves assigning a unique version or identifier to each token issuance. When a user needs to be revoked, all tokens associated with that user are invalidated by incrementing the token version or changing the identifier. This method requires effective tracking and management of token versions.

Token Revocation Management

There are several ways to efficiently manage token revocations. One approach is to maintain a centralized revocation store or database specifically designed to store revoked tokens or token versions. This central store should have efficient indexing and querying capabilities to quickly check if a token has been revoked.

By centralizing the revocation data, the API can easily access and validate token status during the authentication process.

For distributed systems or APIs with multiple instances, a distributed revocation mechanism should be considered. This can involve using shared caches or distributed databases, ensuring that all API instances have access to the revocation data and can perform consistent token revocation checks.

This approach ensures that revocation status is synchronized across all parts of the system, reducing the risk of inconsistent revocation checks.

To keep the revocation list or token versions up to date, be sure to implement a robust process for updates. This process can be triggered by administrative actions, user requests for revocation, or automated procedures in response to token compromise or revocation events.

A well-defined update process ensures that revoked tokens are promptly added to the revocation store, keeping the system’s security up to date and effectively preventing unauthorized access.

Tips for Effective Implementation

First, ensure that the revocation status or token versions persist across system restarts or failures by using durable storage mechanisms or implementing backup and recovery strategies. This ensures that revocation data remains available even in the event of unexpected system interruptions.

Optimize the revocation checks during token validation to minimize performance impact. Consider employing caching mechanisms or in-memory data structures to improve the efficiency of revocation checks, reducing the computational overhead and response time for token validation.

If multiple components or microservices interact with tokens, proper synchronization of revocation information among them is crucial. Ensure that revocation data is consistent across all components to enforce revocation checks uniformly and prevent potential discrepancies in token validation.

Consider storing additional metadata with tokens, such as the issuing authority, expiry time, or other relevant information. This metadata can assist in effective revocation management and auditing, providing valuable insights into token usage and aiding in troubleshooting and security analysis.

For token versioning or expiration-based revocation, provide notifications to users about upcoming token expirations. This proactive approach ensures a seamless user experience and facilitates reauthentication before the token becomes invalid, reducing user frustration and enhancing security.

Security Considerations for Decentralized Security Tokens

When working with decentralized identity tokens, it’s crucial to address important security considerations to ensure the integrity, confidentiality and reliability of the token-based authentication system.

  • Secure token issuance. Implement robust mechanisms for securely issuing tokens. Ensure proper authentication, authorization, and validation of user identity during the token issuance process. Protect the token issuance endpoint from unauthorized access or abuse.
  • Token confidentiality. Safeguard the confidentiality of tokens during transit and storage. Use secure communication channels, such as HTTPS, to prevent eavesdropping and interception of tokens. Store tokens securely on the client side or server side, employing appropriate encryption and access control measures.
  • Token integrity. Ensure the integrity of tokens to prevent tampering and unauthorized modification. Use digital signatures or other cryptographic mechanisms to sign tokens and verify their authenticity during validation. Protect the private keys used for token signing and verification.
  • Token expiry and revocation. Enforce token expiry to limit their validity period and reduce the risk of unauthorized access. Implement token revocation mechanisms, such as blacklisting or token versioning, to invalidate tokens when necessary, such as in case of compromise or user revocation.
  • Transport Layer Security (TLS). Employ secure communication protocols, such as TLS, to encrypt the communication channels between clients, servers and token issuers. Use strong cipher suites and keep the TLS implementation up-to-date to mitigate security vulnerabilities.
  • Input validation. Validate and sanitize input data related to token handling to prevent security vulnerabilities, such as injection attacks or parameter tampering. Validate token claims, perform input filtering and enforce strict data validation practices.
  • Secure token storage. Implement secure storage mechanisms for tokens on the client side or server side. Protect token storage against unauthorized access, ensuring encryption, access control and proper key management practices.
  • Authorization and access controls. Implement robust authorization mechanisms to control access to protected resources based on token claims, roles, or permissions. Enforce access controls at API endpoints and data resources to prevent unauthorized access.
  • Secure token transmission. When transmitting tokens, adhere to secure practices such as not exposing tokens in URLs, avoiding client-side storage of tokens in vulnerable locations (such as local storage), and considering additional security measures like token binding or channel binding to bind tokens to the communication channel.
  • Security auditing and monitoring. Regularly monitor and audit token-related activities, such as token issuance, validation, and revocation events. Log relevant security events for analysis and anomaly detection. Implement security monitoring tools and processes to identify and respond to potential security incidents.
  • Regular updates and patching. Keep the token issuer, validation libraries and underlying systems up-to-date with the latest security patches and updates. Stay informed about any security vulnerabilities or best practices relevant to your token-based authentication system.

The post Secure Go APIs with Decentralized Identity Tokens, Part 3 appeared first on The New Stack.

Read the whole story
alvinashcraft
21 minutes ago
reply
West Grove, PA
Share this story
Delete

Deprecation of Teams live events API on Microsoft Graph

1 Share

We recently announced the deprecation of Teams live events. For our commercial customers, this deprecation is scheduled for September 30, 2024 (government cloud dates will be released at a future date). Up until this date, Teams live events and the corresponding Microsoft Graph APIs will continue to work as they do today. However, after September 30, 2024, all Teams live events services will no longer function. This means users will not be able to schedule or join any Teams live events and all Team live events Microsoft Graph API service calls will stop working after September 30, 2024.

Teams live events will be replaced by a new town hall feature that allows users to create live events built on the meeting infrastructure. This creates a more consistent experience between large scale streaming events (like Teams live events and town halls) and the Teams meetings experience that users are familiar with. Town hall will be backed by new Microsoft Graph APIs that we expect to release in Spring 2024.

Next steps

Until the replacement town hall APIs are available, you won’t be able to convert your applications from Teams live events to town hall. We recommend the following steps:

  1. Review your applications and take inventory of any apps that might be calling Teams live events Microsoft Graph APIs.
  2. Start creating and testing town halls through the Teams client. This will help you become familiar with the new streaming experience so that you can convert your Teams live events to town hall-powered events.
  3. Mark your calendar and look for upcoming news about town halls and the upcoming Microsoft Graph APIs.

When the new town hall APIs are released, we will make an announcement and you can start updating your applications to the new town hall experience.

For more information about Microsoft Graph APIs, visit the Microsoft Graph Dev Center.

Follow us on X | @Microsoft365Dev for the latest news and updates.

The post Deprecation of Teams live events API on Microsoft Graph appeared first on Microsoft 365 Developer Blog.

Read the whole story
alvinashcraft
21 minutes ago
reply
West Grove, PA
Share this story
Delete

Introducing the New .NET MAUI TreeView Control

1 Share

Introducing the New .NET MAUI TreeView Control

In the recent Essential Studio 2023 Volume 3 release, we introduced an innovative TreeView control for our Syncfusion .NET Multi-Platform App UI (MAUI) platform.

The .NET MAUI TreeView, or SfTreeView in the code, is a control designed to display hierarchical data structures within your app. This includes structures such as organizational hierarchies and nested connections. It offers a user-friendly interface for interacting with complex data structures and navigating through multiple levels of information. It allows users to expand and collapse nodes, revealing or concealing underlying information as needed.

This new control significantly enhances how you present hierarchical data, improving navigation within your .NET MAUI apps. Whether you’re an experienced .NET developer or just starting, we invite you to explore the capabilities of this exciting new control with us.

Stay with us as we delve deeper into the features and benefits of the .NET MAUI TreeView control!

Key features

The .NET MAUI TreeView control offers a variety of user-friendly features, including:

Data population—bound and unbound modes

You can populate the .NET MAUI TreeView with a data source using the SfTreeView.ItemsSource property, or you can create and add the TreeViewNode in a hierarchical structure to the SfTreeView.Nodes property.

Selection

The TreeView lets users select items either programmatically or through touch interactions using the SfTreeView.SelectionMode property. The property must not be set to None. The control supports different selection modes to perform selection operations:

  • None: Disable selection.
  • SelectionMode.Single:  Users can select only a single item. When they click on the selected item, the selection will not be cleared. This is the default value for SelectionMode.
  • SelectionMode.SingleDeselect: Users can select only a single item. When clicking on the selected item, the selection is cleared.
  • SelectionMode.Multiple:  Users can select more than one item. Selection is not cleared when selecting more than one item. A selection can be cleared by clicking on it again.
  • SelectionMode.Extended:  Users can select multiple items using the common key modifiers.
    Selecting an item in .NET MAUI TreeView control
    Selecting an item in the .NET MAUI TreeView control

Item templating

The .NET MAUI TreeView allows you to customize the appearance of the content view and expander view by setting the SfTreeView.ItemTemplate and SfTreeView.ExpanderTemplate properties.

Expand and collapse nodes

You can expand and collapse the nodes in the TreeView programmatically or through user interaction:

  • ExpandActionTarget: Expanding and collapsing of nodes can be performed by tapping the expander view or content view by setting the SfTreeView.ExpandActionTarget property:
    • ExpandActionTarget.Expander: Users can expand and collapse nodes by tapping the expander.
    • ExpandActionTarget.Node: Users can expand and collapse nodes by tapping either the expander or the content.
  • AutoExpandMode: By default, the items in the tree view will be in a collapsed state. You can define how the nodes should expand when loading TreeView by using the SfTreeView.AutoExpandMode property. This property is only applicable in bound mode. In unbound mode, you must set the IsExpanded property to true while creating the nodes. Define the SfTreeView.AutoExpandMode property with:
    • AutoExpandMode.RootNodesExpanded: Expands only the root items when loaded.
    • AutoExpandMode.AllNodesExpanded: Expands all items when loaded.
    • AutoExpandMode.None: When the TreeView loads, it initially collapses all items. Despite this, you or the user can manually or programmatically expand these items. This feature offers significant flexibility in how you present and interact with your data in the TreeView.
  • Programmatic expand and collapse: The TreeView also allows programmatic expansion and collapse based on the TreeViewNode and level using the following methods:
      • ExpandNode(TreeViewNode item): To expand the particular TreeViewNode passed to it.
      • CollapseNode(TreeViewNode item): To collapse the particular TreeViewNode passed to it.
      • ExpandNodes(int level): To expand all items of a level passed to it.
      • CollapseNodes(int level): To collapse all items of a level passed to it.
      • ExpandAll(): To expand all the items in the TreeView.
      • CollapseAll(): To collapse all the items in the TreeView.
    Expanding and collapsing items in .NET MAUI TreeView control

Getting started with the .NET MAUI TreeView control

We have seen the top features of the .NET MAUI TreeView control. Now, let’s see how to add it to your application.

Step 1: Create a .NET MAUI project

First, create a .NET MAUI project.

Step 2: Add the .NET MAUI TreeView NuGet package

Syncfusion .NET MAUI controls are available in the NuGet gallery. To add the .NET MAUI TreeView control to your project, open the NuGet package manager in Visual Studio, and search for Syncfusion.Maui.TreeView, and then install it.

Step 3: Register the handler

In the MauiProgram.cs file, register the handler for Syncfusion core. Refer to the following code.

using Syncfusion.Maui.Core.Hosting;

public static class MauiProgram
{
   public static MauiApp CreateMauiApp()
   {
	var builder = MauiApp.CreateBuilder();
	builder
	  .UseMauiApp<App>()
	  .ConfigureSyncfusionCore()
	  .ConfigureFonts(fonts =>
	   {
		fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
		fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                fonts.AddFont("Roboto-Medium.ttf", "Roboto-Medium");
                fonts.AddFont("Roboto-Regular.ttf", "Roboto-Regular");
            });
	return builder.Build();
   }
}

Step 4: Add the namespaces

Add the Syncfusion.Maui.TreeView and Syncfusion.TreeView.Engine namespaces in your XAML page.

<xmlns:syncfusion ="clr-namespace:Syncfusion.Maui.TreeView;assembly=Syncfusion.Maui.TreeView"
     xmlns:treeviewengine="clr-namespace:Syncfusion.TreeView.Engine;assembly=Syncfusion.Maui.TreeView"/>

Step 5: Define the TreeView control

Add the .NET MAUI TreeView control using the included namespace.

<syncfusion:SfTreeView x:Name="treeView"/>

Step 6: Define the TreeView nodes

To build a tree view, you can use the TreeView control and a hierarchical structure of TreeViewNode objects. This tree structure is established by adding one or more root nodes to the SfTreeView.Nodes collection (without a data source, in unbound mode).

Refer to the following code example.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:syncfusion="clr-namespace:Syncfusion.Maui.TreeView;assembly=Syncfusion.Maui.TreeView"
             xmlns:treeviewengine="clr-namespace:Syncfusion.TreeView.Engine;assembly=Syncfusion.Maui.TreeView"
             x:Class="TreeViewMaui.MainPage">
<ContentPage.Content>
    <syncfusion:SfTreeView x:Name="treeView" ExpandActionTarget="Node" FullRowSelect="True">
        <syncfusion:SfTreeView.Nodes>
            <treeviewengine:TreeViewNode Content="Australia" IsExpanded="True">
                <treeviewengine:TreeViewNode.ChildNodes>
                    <treeviewengine:TreeViewNode Content="New South Wales" IsExpanded="True">
                        <treeviewengine:TreeViewNode.ChildNodes>
                            <treeviewengine:TreeViewNode Content="Sydney" IsExpanded="True"/>
                            <treeviewengine:TreeViewNode Content="Wollongong" IsExpanded="True"/>
                            <treeviewengine:TreeViewNode Content="Newcastle–Maitland" IsExpanded="True"/>
                        </treeviewengine:TreeViewNode.ChildNodes>
                    </treeviewengine:TreeViewNode>
                    <treeviewengine:TreeViewNode Content="Victoria" IsExpanded="True">
                        <treeviewengine:TreeViewNode.ChildNodes>
                            <treeviewengine:TreeViewNode Content="Melbourne" IsExpanded="True"/>
                        </treeviewengine:TreeViewNode.ChildNodes>
                    </treeviewengine:TreeViewNode>
                    <treeviewengine:TreeViewNode Content="Queensland" IsExpanded="True">
                        <treeviewengine:TreeViewNode.ChildNodes>
                            <treeviewengine:TreeViewNode Content="Brisbane" IsExpanded="True"/>
                        </treeviewengine:TreeViewNode.ChildNodes>
                    </treeviewengine:TreeViewNode>
                    <treeviewengine:TreeViewNode Content="Western Australia" IsExpanded="True">
                        <treeviewengine:TreeViewNode.ChildNodes>
                            <treeviewengine:TreeViewNode Content="Perth"/>
                        </treeviewengine:TreeViewNode.ChildNodes>
                    </treeviewengine:TreeViewNode>
                    <treeviewengine:TreeViewNode Content="South Australia" IsExpanded="True">
                        <treeviewengine:TreeViewNode.ChildNodes>
                            <treeviewengine:TreeViewNode Content="Adelaide"/>
                        </treeviewengine:TreeViewNode.ChildNodes>
                    </treeviewengine:TreeViewNode>
                    </treeviewengine:TreeViewNode.ChildNodes>
                </treeviewengine:TreeViewNode>
                <treeviewengine:TreeViewNode Content="Brazil" IsExpanded="True">
                    <treeviewengine:TreeViewNode.ChildNodes>
                        <treeviewengine:TreeViewNode Content="São Paulo" IsExpanded="True">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="São Paulo"/>
                                <treeviewengine:TreeViewNode Content="Campinas"/>
                                <treeviewengine:TreeViewNode Content="Sorocaba"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Rio de Janeiro"/>
                        <treeviewengine:TreeViewNode Content="Minas Gerais">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Belo Horizonte"/>
                                <treeviewengine:TreeViewNode Content="Distrito Federal e Entorno (Brasilia)"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Ceará">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Fortaleza"/>
                                <treeviewengine:TreeViewNode Content="Caucaia"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Paraná">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Curitiba"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                    </treeviewengine:TreeViewNode.ChildNodes>
                </treeviewengine:TreeViewNode>
                <treeviewengine:TreeViewNode Content="China" IsExpanded="True">
                    <treeviewengine:TreeViewNode.ChildNodes>
                        <treeviewengine:TreeViewNode Content="Guangdong">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Guanghou"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Jingjinji">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Beijing"/>
                                <treeviewengine:TreeViewNode Content="Tianjin"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Yangtze River Delta">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Shanghai"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Chengyu">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Chongqing"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Zhejiang Province">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Hangzhou"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                    </treeviewengine:TreeViewNode.ChildNodes>
                </treeviewengine:TreeViewNode>
                <treeviewengine:TreeViewNode Content="United States of America" IsExpanded="True">
                    <treeviewengine:TreeViewNode.ChildNodes>
                        <treeviewengine:TreeViewNode Content="New York"/>
                        <treeviewengine:TreeViewNode Content="California">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Los Angeles"/>
                                <treeviewengine:TreeViewNode Content="San Jose"/>
                                <treeviewengine:TreeViewNode Content="San Francisco"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Illinois">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Chicago"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Texas">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Houston"/>
                                <treeviewengine:TreeViewNode Content="San Antonio"/>
                                <treeviewengine:TreeViewNode Content="Dallas"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Pennsylvania">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Philadelphia"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                    </treeviewengine:TreeViewNode.ChildNodes>
                </treeviewengine:TreeViewNode>
                <treeviewengine:TreeViewNode Content="India" IsExpanded="True">
                    <treeviewengine:TreeViewNode.ChildNodes>
                        <treeviewengine:TreeViewNode Content="Delhi">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="New Delhi"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Maharashtra">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Mumbai"/>
                                <treeviewengine:TreeViewNode Content="Pune"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="West Bengal">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Kolkatta"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Karnataka">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Bangalore"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                        <treeviewengine:TreeViewNode Content="Tamil Nadu">
                            <treeviewengine:TreeViewNode.ChildNodes>
                                <treeviewengine:TreeViewNode Content="Chennai"/>
                            </treeviewengine:TreeViewNode.ChildNodes>
                        </treeviewengine:TreeViewNode>
                    </treeviewengine:TreeViewNode.ChildNodes>
                </treeviewengine:TreeViewNode>
            </syncfusion:SfTreeView.Nodes>
        </syncfusion:SfTreeView>
    </ContentPage.Content>

</ContentPage>

Refer to the following output image.

Populating items in .NET MAUI TreeView control using unbound mode
Populating items in .NET MAUI TreeView control using unbound mode

Data population—bound mode

The .NET MAUI TreeView also enables binding data by using the ItemsSource property. To achieve this, please follow these steps.

Step 1: Create a data model

Create a simple data model to bind the data for the TreeView, as shown in the following code example.

public class FileManager : INotifyPropertyChanged
{
    #region Fields

    private string itemName;
    private ImageSource imageIcon;
    private ObservableCollection<FileManager> subFiles;

    #endregion

    #region Constructor
    public FileManager()
    {
    }

    #endregion

    #region Properties
    public ObservableCollection<FileManager> SubFiles
    {
        get { return subFiles; }
        set
        {
            subFiles = value;
            RaisedOnPropertyChanged("SubFiles");
        }
    }

    public string ItemName
    {
        get { return itemName; }
        set
        {
            itemName = value;
            RaisedOnPropertyChanged("ItemName");
        }
    }

    public ImageSource ImageIcon
    {
        get { return imageIcon; }
        set
        {
            imageIcon = value;
            RaisedOnPropertyChanged("ImageIcon");
        }
    }

    #endregion

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisedOnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #endregion

Step 2: Create the view model

Create a FileManagerViewModel class with a Files collection property initialized with 20 data objects, as shown in the following code example.

public class FileManagerViewModel
{
    #region Fields

    private ObservableCollection<FileManager> files;

    #endregion

    #region Constructor

    public FileManagerViewModel()
    {
        GenerateSource();
    }

    #endregion

    #region Properties

    public ObservableCollection<FileManager> Files
    {
        get { return files; }
        set { this.files = value; }
    }

    #endregion

    #region Generate Source

    private void GenerateSource()
    {
        var nodeImageInfo = new ObservableCollection<FileManager>();
      
        var doc = new FileManager() { ItemName = "Documents", ImageIcon = "folder.png" };
        var download = new FileManager() { ItemName = "Downloads", ImageIcon = "folder.png" };
        var mp3 = new FileManager() { ItemName = "Music", ImageIcon ="folder.png" };
        var pictures = new FileManager() { ItemName = "Pictures", ImageIcon = "folder.png" };
        var video = new FileManager() { ItemName = "Videos", ImageIcon ="folder.png" };

        var pollution = new FileManager() { ItemName = "Environmental Pollution.docx", ImageIcon = "word.png" };
        var globalWarming = new FileManager() { ItemName = "Global Warming.ppt", ImageIcon = "ppt.png" };
        var sanitation = new FileManager() { ItemName = "Sanitation.docx", ImageIcon = "word.png"};
        var socialNetwork = new FileManager() { ItemName = "Social Network.pdf", ImageIcon ="pdfimage.png" };
        var youthEmpower = new FileManager() { ItemName = "Youth Empowerment.pdf", ImageIcon = "pdfimage.png" };

       
        var tutorials = new FileManager() { ItemName = "Tutorials.zip", ImageIcon = "zip.png" };
        var typeScript = new FileManager() { ItemName = "TypeScript.7z", ImageIcon ="zip.png" };
        var uiGuide = new FileManager() { ItemName = "UI-Guide.pdf", ImageIcon = "pdfimage.png"};

        var song = new FileManager() { ItemName = "Gouttes", ImageIcon = "audio.png" };

        var camera = new FileManager() { ItemName = "Camera Roll", ImageIcon = "folder.png" };
        var stone = new FileManager() { ItemName = "Stone.jpg", ImageIcon = "image.png" };
        var wind = new FileManager() { ItemName = "Wind.jpg", ImageIcon = "image.png"};

        var img0 = new FileManager() { ItemName = "WIN_20160726_094117.JPG", ImageIcon = "people_circle23.png" };
        var img1 = new FileManager() { ItemName = "WIN_20160726_094118.JPG", ImageIcon = "people_circle2.png" };

        var video1 = new FileManager() { ItemName = "Naturals.mp4", ImageIcon = "video.png" };
        var video2 = new FileManager() { ItemName = "Wild.mpeg", ImageIcon = "video.png" };       doc.SubFiles = new ObservableCollection<FileManager>
       {
           pollution,
           globalWarming,
           sanitation,
           socialNetwork,
           youthEmpower
       };

       download.SubFiles = new ObservableCollection<FileManager>
       {
           tutorials,
           typeScript,
           uiGuide
       };

       mp3.SubFiles = new ObservableCollection<FileManager>
       {
           song
       };

       pictures.SubFiles = new ObservableCollection<FileManager>
       {
           camera,
           stone,
           wind
       };
       camera.SubFiles = new ObservableCollection<FileManager>
       {
           img0,
           img1
       };

       video.SubFiles = new ObservableCollection<FileManager>
       {
           video1,
           video2
       };

       nodeImageInfo.Add(doc);
       nodeImageInfo.Add(download);
       nodeImageInfo.Add(mp3);
       nodeImageInfo.Add(pictures);
       nodeImageInfo.Add(video);
       files = nodeImageInfo;
   }

   #endregion
}

Step 3: Set the binding context

Then, set the FileManagerViewModel class instance as the BindingContext of your page to bind its properties to the TreeView.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:syncfusion="clr-namespace:Syncfusion.Maui.TreeView;assembly=Syncfusion.Maui.TreeView"
             xmlns:local="clr-namespace:TreeViewMaui"
             x:Class="TreeViewMaui.MainPage">

    <ContentPage.BindingContext>
        <local:FileManagerViewModel x:Name="viewModel"/>
    </ContentPage.BindingContext>
</ContentPage>

Step 4: Bind data collection to TreeView

You can now use the ItemsSource property to bind data to the SfTreeView by filling it with a hierarchical data source. The SfTreeView.ChildPropertyName property can be used to set the name of the child objects.

Refer to the following code example.

<syncfusion:SfTreeView x:Name="treeView" 
                       ChildPropertyName="SubFiles"
                       ItemsSource="{Binding Files}">

Step 5: Define the tree view items

Refer to the following code example. In it, we create a custom user interface (UI) to display the data items by using the ItemTemplate property.

<syncfusion:SfTreeView x:Name="treeView" 
                       ChildPropertyName="SubFiles"
                       ItemsSource="{Binding Files}"  
                       AutoExpandMode="AllNodesExpanded">

    <syncfusion:SfTreeView.ItemTemplate>
        <DataTemplate>
            <Grid x:Name="grid" RowSpacing="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="40" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Grid Grid.Column="0">
                    <Image Source="{Binding ImageIcon}"
                           VerticalOptions="Center"
                           HorizontalOptions="Center"
                           HeightRequest="24" 
                           WidthRequest="24"/>
                </Grid>
                <Grid Grid.Column="1">
                    <Label LineBreakMode="NoWrap"
                           Text="{Binding ItemName}"
                           VerticalTextAlignment="Center">
                    </Label>
                </Grid>
            </Grid>
        </DataTemplate>
    </syncfusion:SfTreeView.ItemTemplate>
</syncfusion:SfTreeView>

After executing the previous code examples, we’ll get a TreeView like in the following image.

Populating items in .NET MAUI TreeView control using the bound mode
Populating items in .NET MAUI TreeView control using the bound mode

GitHub references

For more details, refer to the populating nodes in unbound and bound modes in .NET MAUI TreeView demos on GitHub.

Conclusion

Thanks for reading! In this blog, we’ve explored the features of the new Syncfusion .NET MAUI TreeView control, unveiled in the 2023 Volume 3 release. Details about this control are also available on our Release Notes and What’s New pages. We encourage you to try out the control and share your thoughts in the comments below!

To start evaluating this control immediately, download Essential Studio for .NET MAUI.

For questions, you can contact us via our support forumsupport portal, or feedback portal. We’re always here to assist you!

Related blogs

Read the whole story
alvinashcraft
21 minutes ago
reply
West Grove, PA
Share this story
Delete

Postgres 16 available in Azure Cosmos DB for PostgreSQL, powered by Citus

1 Share

Big news in the Postgres world: PostgreSQL 16 was released just over 2 weeks ago. And today we’re announcing that Postgres 16 is generally available for production workloads on Azure Cosmos DB for PostgreSQL. That’s right, in production: this announcement is not just a preview of Postgres 16 support. 

Whether you need to provision a new distributed Postgres cluster in Azure Cosmos DB for PostgreSQL—or upgrade your existing database clusters—Postgres 16 is now an option for you.  

And you can use Azure Portal, Bicep or ARM templates, REST APIs, Azure SDKs, or Azure CLI to spin up a new Postgres 16 cluster in Azure Cosmos DB for PostgreSQL, or to upgrade an existing cluster to Postgres 16. 

PostgreSQL 16 + Citus 12 now available in Azure Cosmos DB for PostgreSQL  

Giving you access to new capabilities in Postgres is a priority for the Azure Cosmos DB for PostgreSQL team. And because Citus—which powers Azure Cosmos DB for PostgreSQL—is an open source database extension (and not a fork!), it makes it easier for us to keep Azure Cosmos DB for PostgreSQL current with the latest Postgres releases.  

A lot of focused engineering work to keep up-to-date with the Postgres 16 beta and RC candidate releases over the last months allowed to bring all Postgres 16 benefits to Citus extension and Azure Cosmos DB for PostgreSQL that fast. In fact, the Citus 12.1 open source release came out with Postgres 16 support just 1 week after the Postgres 16 release.

Of course, making Azure Cosmos DB for PostgreSQL available on the latest versions of Postgres also involves a rigorous QA process, too. Here are some details about the QA and release process published last year for Azure Cosmos DB for PostgreSQL, shortly after Postgres 15 was released. 

Lots of improvements, small and large, in Postgres 16 

Highlights of the innovations featured in the PostgreSQL 16 release notes (that many of us are excited about) include: 

  • query performance improvements with more parallelism;  
  • developer experience enhancements;  
  • monitoring of I/O stats using pg_stat_io view; and  
  • enhanced security features 
  • and more…. 

Not only PostgreSQL 16 

While some workloads get tangible benefits from the latest Postgres versions, other applications are just fine running on an older PostgreSQL version. Which is why Azure Cosmos DB for PostgreSQL supports all current Postgres versions: Postgres 11, 12, 13, 14, 15, and now 16. “All current Postgres versions” means all the PostgreSQL versions that are supported by PostgreSQL community.  

And if you run your cluster on PostgreSQL 14 or 15, you also get access to the latest version of the Citus database extension: Citus 12.x. 

Learn more about PostgreSQL 16 and Azure Cosmos DB for PostgreSQL 

If you want to give Azure Cosmos DB for PostgreSQL a try, start with the Quickstart or free trial. More links and resources below. Happy hacking! 

Figure 1: Screenshot from the Azure portal of an Azure Cosmos DB for PostgreSQL cluster running PostgreSQL 16 (and powered by Citus 12.1.)
Figure 1: Screenshot from the Azure portal of an Azure Cosmos DB for PostgreSQL cluster running PostgreSQL 16 (and powered by Citus 12.1.) 

The post Postgres 16 available in Azure Cosmos DB for PostgreSQL, powered by Citus appeared first on Azure Cosmos DB Blog.

Read the whole story
alvinashcraft
22 minutes ago
reply
West Grove, PA
Share this story
Delete

Difference between .Net7 and .Net8 | Between .NET 7 and .NET8 Which version we should prefer in programming

1 Share

 .NET 7 and .NET 8 are both versions related to the .NET platform and there are a couple of key differences between them.

Support

.NET 7 is the standard-term support (STS) release, which means it will be supported for 18 months.

.NET 8 is the long-term support (LTS) release, which means it will be supported for three years. This makes .NET 8 a better choice for developers who need long-term stability and support for their applications.

Performance

.NET 8 builds on the performance enhancements introduced in .NET 7 by further optimizing the Just-In-Time (JIT) compiler, garbage collector, and runtime. The result is faster startup times, better overall application performance, and reduced memory usage.

New features

.NET 8 includes a number of new features and enhancements, such as:

  • Support for SIMD (single instruction, multiple data) operations on 512-bit vectors. This can significantly improve the performance of applications that perform data-intensive operations, such as machine learning and scientific computing.
  • Support for the Intel Advanced Vector Extensions 512 (AVX-512) instructions. AVX-512 is a new set of vector instructions that provides additional performance benefits for data-intensive applications.
  • Enhanced diagnostics capabilities, including new tools and features for debugging and troubleshooting performance problems.
  • Expanded cross-platform support, including improvements to the Mono runtime and new features for building and deploying .NET applications on macOS and Linux.
  • Advanced language features, such as support for global using directives and record structs.



Here is a feature difference between .NET 7 and .NET 8 with a programming example:

Feature.NET 7.NET 8
SupportStandard-term support (STS)Long-term support (LTS)
PerformanceJIT compiler, garbage collector, and runtime optimizationsAdditional JIT compiler, garbage collector, and runtime optimizations; support for SIMD operations on 512-bit vectors and Intel AVX-512 instructions
New featuresRaw string literals, generic math interfaces, and support for nullable annotations in Microsoft.Extensions.* libraries, new Tar APIsSupport for global using directives, record structs, SIMD operations on 512-bit vectors and Intel AVX-512 instructions, enhanced diagnostics capabilities, expanded cross-platform support

Programming example

The following code shows a simple example of using the new SIMD support in .NET 8:

using System;
using System.Numerics;

public class Program
{
    public static void Main(string[] args)
    {
        // Create a new Vector<float> object.
        Vector<float> values = new Vector<float>(1f, 2f, 3f, 4f);

        // Add the elements of the vector together.
        float sum = Vector.Sum(values);

        // Display the result.
        Console.WriteLine($"The sum of given vector elements is {sum}.");
    }
}

This code will compile and run on .NET 8, but it will not compile on .NET 7.

Support for global using directives in .NET 8

The global directive can be used to import any namespace, including the using System.Numerics namespace in this example. This means that you can use the Vector type without having to qualify it with the namespace name.

Global using directives can be placed at the top of any source file, but they are typically placed in a single file, such as a GlobalUsings.cs file. This makes it easy to manage your global using directives and keep them consistent across your project.

Global using directives can be a useful way to reduce the amount of boilerplate code in your source files. They can also make your code more concise and readable.

// Create a new global using directive.
global using System.Numerics;

public class Program
{
    public static void Main(string[] args)
    {
        // Create a new Vector<float> object.
        Vector<float> values = new Vector<float>(1f, 2f, 3f, 4f);

        // Add the elements of the vector together.
        float sum = Vector.Sum(values);

        // Display the result.
        Console.WriteLine($"The sum of given vector elements is {sum}.");
    }
}

Record structs in .NET 8:

Record structs are a new type of struct in .NET 8 that are designed to be immutable and lightweight. They are similar to classes, but they have a number of advantages, including:

  • Record structs are immutable by default, which means that their fields cannot be changed once they are initialized. This makes them ideal for use in scenarios where data needs to be shared and protected from modification.
  • Record structs are lightweight and efficient because they do not have any overhead associated with inheritance or polymorphism.
  • Record structs provide a number of syntactic benefits, such as concise syntax for creating instances and accessing fields.

To create a record struct, you use the record keyword followed by the name of the struct and a list of its fields. Each field must have a type and a name.

Record structs can be used in any scenario where you would use a regular struct or class. However, they are particularly well-suited for use in scenarios where data needs to be shared and protected from modification, or where performance is important.

Here are some examples of how record structs can be used:

  • To represent data that is read from a database or other external source.
  • To represent immutable values, such as points in space or colors.
  • To represent data that is passed between different parts of a program.
  • To implement data structures, such as linked lists and hash tables.

Record structs are a powerful new feature in .NET 8 that can be used to write cleaner, more efficient, and more robust code.

public record Person(string Name, int Age);

public class Program
{
    public static void Main(string[] args)
    {
        // Create a new Person record.
        Person p = new Person("Alice", 25);

        //Print name and age of the person.
        Console.WriteLine($"{p.Name} is {p.Age} years old.");
    }
}

Enhanced diagnostics capabilities in.Net8

The enhanced diagnostics capabilities in .NET 8 include a number of new features and improvements, such as:

  • Improved support for ActivityScope. ActivityScope is a new class in .NET 8 that makes it easier to track the execution of activities. This can be useful for debugging and troubleshooting performance problems.
  • New Activity tags. Activity tags are a way to store additional information about an activity. .NET 8 includes a number of new Activity tags, such as "error" and "duration." These tags can be used to provide more context when debugging and troubleshooting problems.
  • Enhanced ActivityContext. The ActivityContext class in .NET 8 has been enhanced to provide more information about the current activity. This information can be used to debug and troubleshoot problems and to make more informed decisions about how to handle errors.

The example code above shows how to use the new ActivityScope class and Activity tags to track the execution of an activity. The example also shows how to get the ActivityContext for the current thread and display its contents.

You can use the enhanced diagnostics capabilities in .NET 8 to improve the debugging and troubleshooting of your applications. This can lead to faster and more efficient development cycles.

using System;
using System.Diagnostics;

public class Program
{
    public static void Main(string[] args)
    {
        // Start a new ActivityScope.
        using (ActivityScope scope = new ActivityScope("My Activity"))
        {
            // Perform some work.
            try
            {
                // Do something that might fail.
            }
            catch (Exception ex)
            {
                // Log the exception.
                Activity.Current?.AddTag("error", ex.ToString());
            }
        }

        // Get the ActivityContext for the current thread.
        ActivityContext context = Activity.Current?.Context;

        // Display the ActivityContext.
        Console.WriteLine(context.ToString());
    }
}

Expanded cross-platform support in .net 8

The expanded cross-platform support in .NET 8 includes a number of new features and improvements, such as:

  • Support for ARM64 architecture. .NET 8 now supports the ARM64 architecture, which is used in a variety of devices, such as smartphones, tablets, and laptops. This means that you can now build and deploy .NET applications to a wider range of devices.
  • Improved support for macOS and Linux. .NET 8 includes a number of improvements to the Mono runtime, which is used to run .NET applications on macOS and Linux. These improvements include better performance and compatibility.
  • New tools for building and deploying cross-platform applications. .NET 8 includes a number of new tools for building and deploying cross-platform applications, such as the .NET CLI and the .NET Build Tools. These tools make it easier to build and deploy .NET applications to a variety of platforms.

The example code above shows how to use the new HttpClient class to make a web request. The HttpClient class is a cross-platform class that can be used to make web requests from Windows, macOS, and Linux.

You can use the expanded cross-platform support in .NET 8 to build and deploy your applications to a wider range of devices and platforms. This can help you to reach a wider audience and grow your business.

using System;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main(string[] args)
    {
        // Create a new HttpClient object.
        HttpClient client = new HttpClient();

        // Get the contents of a web page.
        HttpResponseMessage response = await client.GetAsync("https://www.microsoft.com");

        // print the contents of the web page.
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}

Conclusion

.NET 8 is a significant release of the .NET platform that offers a number of new features and enhancements, as well as performance improvements and long-term support. Developers who are looking for a stable and supported platform for their applications should consider using .NET 8.

----------------------------------------------------------
Read the whole story
alvinashcraft
22 minutes ago
reply
West Grove, PA
Share this story
Delete
Next Page of Stories