{"id":1746,"date":"2025-02-20T18:16:51","date_gmt":"2025-02-20T18:16:51","guid":{"rendered":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2025\/02\/20\/net-maui-performance-features-in-net-9\/"},"modified":"2025-02-20T18:16:51","modified_gmt":"2025-02-20T18:16:51","slug":"net-maui-performance-features-in-net-9","status":"publish","type":"post","link":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2025\/02\/20\/net-maui-performance-features-in-net-9\/","title":{"rendered":".NET MAUI Performance Features in .NET 9"},"content":{"rendered":"<p>.NET Multi-platform App UI (.NET MAUI) continues to evolve with each<br \/>\nrelease, and .NET 9 brings a focus on trimming and a new supported<br \/>\nruntime: NativeAOT. These features can help you reduce application<br \/>\nsize, improve startup times, and ensure your applications run smoothly<br \/>\non various platforms. Both developers looking to optimize their .NET<br \/>\nMAUI applications and NuGet package authors are able to take advantage<br \/>\nof these features in .NET 9.<\/p>\n<p>We\u2019ll also walk through the options available to you as a developer<br \/>\nfor measuring the performance of your .NET MAUI applications. Both CPU<br \/>\nsampling and memory snapshots are available via dotnet-trace and<br \/>\ndotnet-gcdump respectively. These can give insights into performance<br \/>\nproblems in your application, NuGet packages, or even something we<br \/>\nshould look into for .NET MAUI.<\/p>\n<h2>Background<\/h2>\n<p>By default, .NET MAUI applications on iOS and Android use the<br \/>\nfollowing settings:<\/p>\n<p>\u201cSelf-contained\u201d, meaning a copy of the BCL and runtime are included<br \/>\nwith the application.<\/p>\n<div class=\"alert alert-primary\">\n<p class=\"alert-divider\"><strong>Note<\/strong><\/p>\n<p>This makes .NET MAUI applications suitable for running on \u201capp stores\u201d as no prerequisites such as installing a .NET runtime are required.<\/p><\/div>\n<p>Partially trimmed (TrimMode=partial), meaning that code within<br \/>\nyour applications or NuGet packages are not trimmed by default.<\/p>\n<div class=\"alert alert-primary\">\n<p class=\"alert-divider\"><strong>Note<\/strong><\/p>\n<p>This is a good default, as it is the most compatible with existing code and NuGet packages in the ecosystem.<\/p><\/div>\n<h2>Full Trimming<\/h2>\n<p>This is where full-trimming (TrimMode=full) can make an impact on<br \/>\nyour application\u2019s size. If you have a substantial amount of C# code<br \/>\nor NuGet packages, you may be missing out on a significant application<br \/>\nsize reduction.<\/p>\n<p>To opt into full trimming, you can add the following to your .csproj file:<\/p>\n<p>&lt;PropertyGroup&gt;<br \/>\n  &lt;TrimMode&gt;full&lt;\/TrimMode&gt;<br \/>\n&lt;\/PropertyGroup&gt;<\/p>\n<p>For an idea on the impact of full trimming:<\/p>\n\n<div class=\"alert alert-primary\">\n<p class=\"alert-divider\"><strong>Note<\/strong><\/p>\n<p> <a href=\"https:\/\/github.com\/jonathanpeppers\/MyPal\">MyPal<\/a> is a sample .NET MAUI application that is a useful comparison because of its usage of several common NuGet packages.<\/p><\/div>\n<p>See our <a href=\"https:\/\/learn.microsoft.com\/dotnet\/maui\/deployment\/trimming\">trimming .NET MAUI documentation<\/a> for more<br \/>\ninformation on \u201cfull\u201d trimming.<\/p>\n<h2>NativeAOT<\/h2>\n<p>Building upon full trimming, NativeAOT both relies on libraries being<br \/>\ntrim-compatible <em>and<\/em> AOT-compatible. NativeAOT is a new runtime that<br \/>\ncan improve startup time and reduce application size compared to<br \/>\nexisting runtimes.<\/p>\n\n<div class=\"alert alert-primary\">\n<p class=\"alert-divider\"><strong>Note<\/strong><\/p>\n<p>NativeAOT is not yet supported on Android, but is available on iOS, MacCatalyst, and Windows.<\/p><\/div>\n<p>To opt into NativeAOT:<\/p>\n<p>&lt;PropertyGroup&gt;<br \/>\n  &lt;IsAotCompatible&gt;true&lt;\/IsAotCompatible&gt;<br \/>\n  &lt;PublishAot&gt;true&lt;\/PublishAot&gt;<br \/>\n&lt;\/PropertyGroup&gt;<\/p>\n<p>For an idea on the impact of NativeAOT and application size:<\/p>\n\n<p>And startup performance:<\/p>\n\n<div class=\"alert alert-primary\">\n<p class=\"alert-divider\"><strong>Note<\/strong><\/p>\n<p>macOS on the above graphs is running on MacCatalyst, the default for .NET MAUI applications running on Mac operating systems.<\/p><\/div>\n<p>See our <a href=\"https:\/\/learn.microsoft.com\/dotnet\/maui\/deployment\/nativeaot\">NativeAOT deployment documentation<\/a> for more<br \/>\ninformation about this newly supported runtime.<\/p>\n<h2>NuGet Package Authors<\/h2>\n<p>As a NuGet package author, you may wish for your package to run in<br \/>\neither fully trimmed or NativeAOT scenarios. This can be useful for<br \/>\ndevelopers targeting .NET MAUI, mobile, or even self-contained ASP.NET<br \/>\nmicroservices.<\/p>\n<p>To support NativeAOT, you will need to:<\/p>\n<p>Mark your assemblies as \u201ctrim-compatible\u201d and \u201cAOT-compatible\u201d.<br \/>\nEnable Roslyn analyzers for trimming and NativeAOT.<br \/>\nSolve all the warnings.<\/p>\n<p>Begin with modifying your .csproj file:<\/p>\n<p>&lt;PropertyGroup&gt;<br \/>\n  &lt;IsTrimmable&gt;true&lt;\/IsTrimmable&gt;<br \/>\n  &lt;IsAotCompatible&gt;true&lt;\/IsAotCompatible&gt;<br \/>\n&lt;\/PropertyGroup&gt;<\/p>\n<p>These properties will enable Roslyn analyzers as well as include<br \/>\n[assembly: AssemblyMetadata] information in the resulting .NET<br \/>\nassembly. Depending on your library\u2019s usage of features like<br \/>\nSystem.Reflection, you could have either just a few warnings or<br \/>\npotentially <em>many<\/em> warnings.<\/p>\n<p>See the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/deploying\/trimming\/prepare-libraries-for-trimming\">documentation on preparing libraries for<br \/>\ntrimming<\/a> for more information.<\/p>\n<h2>XAML and Trimming<\/h2>\n<p>Sometimes, taking advantage of NativeAOT in your app can be as easy as<br \/>\nadding a property to your project file. However, for many .NET MAUI<br \/>\napplications, there can be a lot of warnings to solve. The NativeAOT<br \/>\ncompiler removes unnecessary code and metadata to make the app smaller<br \/>\nand faster. However, this requires understanding which types can be<br \/>\ncreated and which methods can and cannot be called at runtime. This is<br \/>\noften impossible to do in code which heavily uses System.Reflection.<br \/>\nThere are two areas in .NET MAUI which fall into this category: XAML<br \/>\nand data-binding.<\/p>\n<h3>Compiled XAML<\/h3>\n<p>Loading XAML at runtime provides flexibility and enables features like<br \/>\nXAML hot reload. XAML can instantiate any class in the whole app, the<br \/>\n.NET MAUI SDK, and referenced NuGet packages. XAML can also set values<br \/>\nto any property.<\/p>\n<p>Conceptually, loading a XAML layout at runtime requires:<\/p>\n<p>Parsing the XML document.<br \/>\nLooking up the control types based on the XML element names using Type.GetType(xmlElementName).<br \/>\nCreating new instances of the controls using Activator.CreateInstance(controlType).<br \/>\nConverting the raw string XML attribute values into the target type of the property.<br \/>\nSetting properties based on the names of the XML attributes.<\/p>\n<p>This process can not only be slow, but it presents a great challenge<br \/>\nfor NativeAOT. For example, the trimmer does not know which types<br \/>\nwould be looked up using the Type.GetType method. This means that<br \/>\neither the compiler would need to keep all the classes from the whole<br \/>\n.NET MAUI SDK and all the NuGet packages in the final app, or the<br \/>\nmethod might not be able to find the types declared in the XML input<br \/>\nand fail at runtime.<\/p>\n<p>Fortunately, .NET MAUI has a solution \u2013 <a href=\"https:\/\/learn.microsoft.com\/dotnet\/maui\/xaml\/xamlc\">XAML compilation<\/a>.<br \/>\nThis turns XAML into the actual code for the InitializeComponent()<br \/>\nmethod at build time. Once the code is generated, the NativeAOT<br \/>\ncompiler has all the information it needs to trim your app.<\/p>\n<p>In .NET 9, we implemented the last remaining XAML features that the<br \/>\ncompiler could not handle in previous releases, especially compiling<br \/>\nbindings. Lastly, if your app relies on loading XAML at runtime,<br \/>\nNativeAOT might not be suitable for your application.<\/p>\n<h3>Compiled Bindings<\/h3>\n<p>A binding ties together a source property with a target property. When<br \/>\nthe source changes, the value is propagated to the target.<\/p>\n<p>Bindings in .NET MAUI are defined using a string \u201cpath\u201d. This path<br \/>\nresembles C# expressions for accessing properties and indexers. When<br \/>\nthe binding is applied to a source object, .NET MAUI uses<br \/>\nSystem.Reflection to follow the path to access the desired source<br \/>\nproperty. This suffers from the same problems as loading XAML at<br \/>\nruntime, because the trimmer does not know which properties could be<br \/>\naccessed by reflection and so it does not know which properties it can<br \/>\nsafely trim from the final application.<\/p>\n<p>When we know the type of the source object at build time from<br \/>\nx:DataType attributes, we can compile the binding path into a simple<br \/>\ngetter method (and a setter method for two-way bindings). The compiler<br \/>\nwill also ensure that the binding listens to any property changes<br \/>\nalong the binding path of properties that implement<br \/>\nINotifyPropertyChanged.<\/p>\n<p>The XAML compiler could already compile most bindings in .NET 8 and<br \/>\nearlier. In .NET 9 we made sure any binding in your XAML code can be<br \/>\ncompiled. Learn more about this feature in the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/maui\/fundamentals\/data-binding\/compiled-bindings\">compiled bindings<br \/>\ndocumentation<\/a>.<\/p>\n<h3>Compiled bindings in C#<\/h3>\n<p>The only supported way of defining bindings in C# code up until .NET 8<br \/>\nhas been using a string-based path. In .NET 9, we are adding a new<br \/>\nAPI which allows us to compile the binding using a source generator:<\/p>\n<p>\/\/ .NET 8 and earlier<br \/>\nmyLabel.SetBinding(Label.TextProperty, &#8220;Text&#8221;);<\/p>\n<p>\/\/ .NET 9<br \/>\nmyLabel.SetBinding(Label.TextProperty, static (Entry nameEntry) =&gt; nameEntry.Text);<\/p>\n<p>The Binding.Create() method is also an option, for when you need to<br \/>\nsave the Binding instance for later use:<\/p>\n<p>var nameBinding = Binding.Create(static (Entry nameEntry) =&gt; nameEntry.Text);<\/p>\n<p>.NET MAUI\u2019s source generator will compile the binding the same way the<br \/>\nXAML compiler does. This way the binding can be fully analyzed by the<br \/>\nNativeAOT compiler.<\/p>\n<p>Even if you aren\u2019t planning to migrate your application to NativeAOT,<br \/>\ncompiled bindings can improve the general performance of the binding.<br \/>\nTo illustrate the difference, let\u2019s use BenchmarkDotNet to measure<br \/>\nthe difference between the calls to SetBinding() on Android using the<br \/>\nMono runtime:<\/p>\n<p>\/\/ dotnet build -c Release -t:Run -f net9.0-android<\/p>\n<p>public class SetBindingBenchmark<br \/>\n{<br \/>\n    private readonly ContactInformation _contact = new ContactInformation(new FullName(&#8220;John&#8221;));<br \/>\n    private readonly Label _label = new();<\/p>\n<p>    [GlobalSetup]<br \/>\n    public void Setup()<br \/>\n    {<br \/>\n        DispatcherProvider.SetCurrent(new MockDispatcherProvider());<br \/>\n        _label.BindingContext = _contact;<br \/>\n    }<\/p>\n<p>    [Benchmark(Baseline = true)]<br \/>\n    public void Classic_SetBinding()<br \/>\n    {<br \/>\n        _label.SetBinding(Label.TextProperty, &#8220;FullName.FirstName&#8221;);<br \/>\n    }<\/p>\n<p>    [Benchmark]<br \/>\n    public void Compiled_SetBinding()<br \/>\n    {<br \/>\n        _label.SetBinding(Label.TextProperty, static (ContactInformation contact) =&gt; contact.FullName?.FirstName);<br \/>\n    }<\/p>\n<p>    [IterationCleanup]<br \/>\n    public void Cleanup()<br \/>\n    {<br \/>\n        _label.RemoveBinding(Label.TextProperty);<br \/>\n    }<br \/>\n}<\/p>\n<p>When I ran the benchmark on Samsung Galaxy S23, I got the following results:<\/p>\n<p>Method<br \/>\nMean<br \/>\nError<br \/>\nStdDev<br \/>\nRatio<br \/>\nRatioSD<\/p>\n<p>Classic_SetBinding<br \/>\n67.81 us<br \/>\n1.338 us<br \/>\n1.787 us<br \/>\n1.00<br \/>\n0.04<\/p>\n<p>Compiled_SetBinding<br \/>\n30.61 us<br \/>\n0.629 us<br \/>\n1.182 us<br \/>\n0.45<br \/>\n0.02<\/p>\n<p>The classic binding needs to first parse the string-based path and<br \/>\nthen use System.Reflection to get the current value of the source.<br \/>\nEach subsequent update of the source property will also be faster with<br \/>\nthe compiled binding:<\/p>\n<p>\/\/ dotnet build -c Release -t:Run -f net9.0-android<\/p>\n<p>public class UpdateValueTwoLevels<br \/>\n{<br \/>\n    ContactInformation _contact = new ContactInformation(new FullName(&#8220;John&#8221;));<br \/>\n    Label _label = new();<\/p>\n<p>    [GlobalSetup]<br \/>\n    public void Setup()<br \/>\n    {<br \/>\n        DispatcherProvider.SetCurrent(new MockDispatcherProvider());<br \/>\n        _label.BindingContext = _contact;<br \/>\n    }<\/p>\n<p>    [IterationSetup(Target = nameof(Classic_UpdateWhenSourceChanges))]<br \/>\n    public void SetupClassicBinding()<br \/>\n    {<br \/>\n        _label.SetBinding(Label.TextProperty, &#8220;FullName.FirstName&#8221;);<br \/>\n    }<\/p>\n<p>    [IterationSetup(Target = nameof(Compiled_UpdateWhenSourceChanges))]<br \/>\n    public void SetupCompiledBinding()<br \/>\n    {<br \/>\n        _label.SetBinding(Label.TextProperty, static (ContactInformation contact) =&gt; contact.FullName?.FirstName);<br \/>\n    }<\/p>\n<p>    [Benchmark(Baseline = true)]<br \/>\n    public void Classic_UpdateWhenSourceChanges()<br \/>\n    {<br \/>\n        _contact.FullName.FirstName = &#8220;Jane&#8221;;<br \/>\n    }<\/p>\n<p>    [Benchmark]<br \/>\n    public void Compiled_UpdateWhenSourceChanges()<br \/>\n    {<br \/>\n        _contact.FullName.FirstName = &#8220;Jane&#8221;;<br \/>\n    }<\/p>\n<p>    [IterationCleanup]<br \/>\n    public void Reset()<br \/>\n    {<br \/>\n        _label.Text = &#8220;John&#8221;;<br \/>\n        _contact.FullName.FirstName = &#8220;John&#8221;;<br \/>\n        _label.RemoveBinding(Label.TextProperty);<br \/>\n    }<br \/>\n}<\/p>\n<p>Method<br \/>\nMean<br \/>\nError<br \/>\nStdDev<br \/>\nRatio<br \/>\nRatioSD<\/p>\n<p>Classic_UpdateWhenSourceChanges<br \/>\n46.06 us<br \/>\n0.934 us<br \/>\n1.369 us<br \/>\n1.00<br \/>\n0.04<\/p>\n<p>Compiled_UpdateWhenSourceChanges<br \/>\n30.85 us<br \/>\n0.634 us<br \/>\n1.295 us<br \/>\n0.67<br \/>\n0.03<\/p>\n<p>The differences for a single binding aren\u2019t that dramatic but they add<br \/>\nup. This can be noticeable on complex pages with many bindings or when<br \/>\nscrolling lists like CollectionView or ListView.<\/p>\n<p>The full <a href=\"https:\/\/github.com\/simonrozsival\/maui9-bindings-benchmark\">source code of the above benchmarks<\/a> is available on GitHub.<\/p>\n<h2>Profiling .NET MAUI Applications<\/h2>\n<p>Attaching dotnet-trace to a .NET MAUI application, allows you to get<br \/>\nprofiling information in formats like .nettrace and .speedscope.<br \/>\nThese give you CPU sampling information about the time spent in each<br \/>\nmethod in your application. This is quite useful for finding where<br \/>\ntime is spent in the startup or general performance of your .NET<br \/>\napplications. Likewise, dotnet-gcdump can take memory snapshots of<br \/>\nyour application that display every managed C# object in memory.<br \/>\ndotnet-dsrouter is a requirement for connecting dotnet-trace to a<br \/>\nremote device, and so this is not needed for desktop applications.<\/p>\n<p>You can install these tools with:<\/p>\n<p>$ dotnet tool install -g dotnet-trace<br \/>\nYou can invoke the tool using the following command: dotnet-trace<br \/>\nTool &#8216;dotnet-trace&#8217; was successfully installed.<br \/>\n$ dotnet tool install -g dotnet-dsrouter<br \/>\nYou can invoke the tool using the following command: dotnet-dsrouter<br \/>\nTool &#8216;dotnet-dsrouter&#8217; was successfully installed.<br \/>\n$ dotnet tool install -g dotnet-gcdump<br \/>\nYou can invoke the tool using the following command: dotnet-gcdump<br \/>\nTool &#8216;dotnet-gcdump&#8217; was successfully installed.<\/p>\n<p>From here, instructions differ slightly for each platform, but<br \/>\ngenerally the steps are:<\/p>\n<p>Build your application in Release mode. For Android, toggle<br \/>\n&lt;AndroidEnableProfiler&gt;true&lt;\/AndroidEnableProfiler&gt; in your<br \/>\n.csproj file, so the required Mono diagnostic components are<br \/>\nincluded in the application.<br \/>\nIf profiling mobile, run dotnet-dsrouter android (or<br \/>\ndotnet-dsrouter ios, etc.) on your development machine.<br \/>\nConfigure environment variables, so the application can connect to<br \/>\nthe profiler. For example, on Android:<br \/>\n$ adb reverse tcp:9000 tcp:9001<br \/>\n# no output<br \/>\n$ adb shell setprop debug.mono.profile &#8216;127.0.0.1:9000,nosuspend,connect&#8217;<br \/>\n# no output<\/p>\n<p>Run your application.<br \/>\nAttach dotnet-trace (or dotnet-gcdump) to the application,<br \/>\nusing the PID of dotnet-dsrouter:<br \/>\n$ dotnet-trace ps<br \/>\n38604  dotnet-dsrouter  ~\/.dotnet\/tools\/dotnet-dsrouter.exe  ~\/.dotnet\/tools\/dotnet-dsrouter.exe android<\/p>\n<p>$ dotnet-trace collect -p 38604 &#8211;format speedscope<br \/>\nNo profile or providers specified, defaulting to trace profile &#8216;cpu-sampling&#8217;<\/p>\n<p>Provider Name                           Keywords            Level               Enabled By<br \/>\nMicrosoft-DotNETCore-SampleProfiler     0x0000F00000000000  Informational(4)    &#8211;profile<br \/>\nMicrosoft-Windows-DotNETRuntime         0x00000014C14FCCBD  Informational(4)    &#8211;profile <\/p>\n<p>Waiting for connection on \/tmp\/maui-app<br \/>\nStart an application with the following environment variable: DOTNET_DiagnosticPorts=\/tmp\/maui-app<\/p>\n<p>For iOS, macOS, and MacCatalyst, see the <a href=\"https:\/\/github.com\/dotnet\/maui\/wiki\/Profiling-.NET-MAUI-Apps#ios-mac-etc\">iOS profiling wiki<br \/>\npage<\/a> for more information.<\/p>\n\n<div class=\"alert alert-primary\">\n<p class=\"alert-divider\"><strong>Note<\/strong><\/p>\n<p>For Windows applications, you might just consider using Visual Studio\u2019s built-in profiling tools, but dotnet-trace collect &#8212; C:pathtoanexecutable.exe is also an option.<\/p><\/div>\n<p>Now that you\u2019ve collected a file containing performance information,<br \/>\nopening them to view the data is the next step:<\/p>\n<p>dotnet-trace by default outputs .nettrace files, which can be<br \/>\nopened in <a href=\"https:\/\/github.com\/microsoft\/perfview\">PerfView<\/a> or Visual Studio.<br \/>\ndotnet-trace collect &#8211;format speedscope outputs .speedscope<br \/>\nfiles, which can be opened in the <a href=\"https:\/\/www.speedscope.app\/\">Speedscope web app<\/a>.<br \/>\ndotnet-gcdump outputs .gcdump files, which can be opened in<br \/>\n<a href=\"https:\/\/github.com\/microsoft\/perfview\">PerfView<\/a> or Visual Studio. Note that there is not<br \/>\ncurrently a good option to open these files on macOS.<\/p>\n<p>In the future, we hope to make profiling .NET MAUI applications easier<br \/>\nin both future releases of the above .NET diagnostic tooling and<br \/>\nVisual Studio.<\/p>\n\n<div class=\"alert alert-primary\">\n<p class=\"alert-divider\"><strong>Note<\/strong><\/p>\n<p>Note that the NativeAOT runtime does not have support for dotnet-trace and performance profiling. You can use the other supported runtimes for this, or use native profiling tools instead such as Xcode\u2019s Instruments.<\/p><\/div>\n<p>See the <a href=\"https:\/\/aka.ms\/profile-maui\">profiling .NET MAUI wiki page<\/a> for links to<br \/>\ndocumentation on each platform or a <a href=\"https:\/\/youtu.be\/hIYwz5dsZ6M\">profiling demo on<br \/>\nYouTube<\/a> for a full walkthrough.<\/p>\n<h2>Conclusion<\/h2>\n<p>.NET 9 introduces performance enhancements for .NET MAUI applications<br \/>\nthrough full trimming and NativeAOT. These features enable developers<br \/>\nto create more efficient and responsive applications by reducing<br \/>\napplication size and improving startup times. By leveraging tools like<br \/>\ndotnet-trace and dotnet-gcdump, developers can gain insights into<br \/>\ntheir application\u2019s performance.<\/p>\n<p>For a full rundown on .NET MAUI trimming and NativeAOT, see the<br \/>\n<a href=\"https:\/\/youtu.be\/dcUN7c2w-Rg\">.NET Conf 2024 session<\/a> on the topic.<\/p>\n\n<p>The post <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/dotnet-9-performance-improvements-in-dotnet-maui\/\">.NET MAUI Performance Features in .NET 9<\/a> appeared first on <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\">.NET Blog<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>.NET Multi-platform App UI (.NET MAUI) continues to evolve with each release, and .NET 9 brings a focus on trimming [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[7],"tags":[],"class_list":["post-1746","post","type-post","status-publish","format-standard","hentry","category-dotnet"],"_links":{"self":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/1746","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/comments?post=1746"}],"version-history":[{"count":0,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/1746\/revisions"}],"wp:attachment":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media?parent=1746"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/categories?post=1746"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/tags?post=1746"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}