Imhere-Angular-wizard is a component that will make it easy for you to create wizards in your app. You can check a running example of the wizard Demo
در این بین ... اتفاقی رخ نمیدهد و کاربر از پیشرفت عملیات آگاه نمیشود. در این مطلب قصد داریم این وضعیت را بهبود دهیم.
افزودن یک progress-bar به صفحهی آغازین برنامههای Blazor WASM
Blazor امکان دسترسی به چرخهی حیات ابتدایی آنرا نیز میسر کردهاست. برای اینکار ابتدا باید به آن گفت که دریافت خودکار تمام موارد مورد نیاز را انجام نده و ما اینکار را خودمان انجام خواهیم داد:
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
الف) تغییر متن Loading پیشفرض جهت نمایش یک progress-bar
<body> <div id="app"> <div class="d-flex flex-column min-vh-100"> <div class="d-flex vh-100"> <div class="d-flex w-100 justify-content-center align-self-center"> <div class="d-flex flex-column w-25"> <div>Loading <label id="progressbarLabel"></label></div> <div class="progress mt-2" style="height: 2em;"> <div id="progressbar" class="progress-bar progress-bar-striped"></div> </div> </div> </div> </div> </div> </div>
ب) سپس فایل جدید js/blazorLoader.js را با محتوای زیر اضافه میکنیم. در ابتدای این فایل به المانهای progressbar و progressbarLabel طرح فوق اشاره میشود:
(function () { let resourceIndex = 0; const fetchResponsePromises = []; const progressbar = document.getElementById("progressbar"); const progressbarLabel = document.getElementById("progressbarLabel"); const loadStart = new Date().getTime(); if (!isAutostartDisabled()) { console.warn( "`blazor.webassembly.js` script tag doesn`t have the `autostart=false` attribute." ); return; } Blazor.start({ loadBootResource: function (type, filename, defaultUri, integrity) { if (type === "dotnetjs") { progressbarLabel.innerText = filename; return defaultUri; } const responsePromise = fetch(defaultUri, { cache: "no-cache", integrity: integrity, }); fetchResponsePromises.push(responsePromise); responsePromise.then((response) => { if (!progressbar) { console.warn("Couldn't find the progressbar element on the page."); return; } if (!progressbarLabel) { console.warn( "Couldn't find the progressbarLabel element on the page." ); return; } resourceIndex++; const totalResourceCount = fetchResponsePromises.length; const percentLoaded = Math.round( 100 * (resourceIndex / totalResourceCount) ); progressbar.style.width = `${percentLoaded}%`; progressbar.innerText = `${percentLoaded} % [${resourceIndex}/${totalResourceCount}]`; progressbarLabel.innerText = filename; if (percentLoaded >= 100) { var span = new Date().getTime() - loadStart; console.log(`All done in ${span} ms.`); } }); return responsePromise; }, }); function isAutostartDisabled() { var wasmScript = document.querySelector( 'script[src="_framework/blazor.webassembly.js"]' ); if (!wasmScript) { return false; } var autostart = wasmScript.attributes["autostart"]; return autostart && autostart.value === "false"; } })();
<script src="_framework/blazor.webassembly.js" autostart="false"></script> <script src="js/blazorLoader.js"></script> </body>
- محتوای blazorLoader.js، به صورت خود اجرا شونده تهیه شدهاست.
- متد Blazor.start، کار آغاز دستی Blazor WASM و دریافت فایلهای مورد نیاز آنرا انجام میدهد.
- خاصیت loadBootResource آن، به تابعی اشاره میکند که پیشنیازهای اجرایی Blazor WASM را دریافت میکند.
- در متد سفارشی loadBootResource که تهیه کردهایم، responsePromiseها را شمارش کرده و بر اساس تعداد کلی آنها و مواردی که دریافت آنها به پایان رسیدهاست، یک progress-bar را تشکیل و نمایش میدهیم.
- تابع isAutostartDisabled، بررسی میکند که آیا ویژگی autostart مساوی false، به تگ اسکریپت blazor.webassembly.js اضافه شدهاست یا خیر؟
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید: BlazorWasmLoadingBar.zip
- Solution Explorer: touch pad gesture scroll is too sensitive.
- C++/CLI: std::move causes std::unique_ptr parameter to be destructed before function call.
- live share shows "failed to sign in" .
- VS symbol search fails to find symbols.
- Undo randomly stops working.
- VS "Go to defintion" functionality frequently does not work.
- Linux CMake Intellisense HeaderCache not downloading headers for 15.8.0 Preview 4.0.
- When opening a project that requires elevated permissions, Visual Studio does not automatically open the selected project after restarting elevated.
- vcpkgsrv.exe crashes.
- New Visual Studio Code keymap not applying?.
Here’s what’s new in this preview release:
- Smaller SignalR, Blazor Server, and MessagePack scripts
- Enable Redis profiling sessions
- HTTP/3 endpoint TLS configuration
- Initial .NET Hot Reload support
- Razor compiler no longer produces a separate Views assembly
- Shadow-copying in IIS
- Vcpkg port for SignalR C++ client
- Reduced memory footprint for idle TLS connections
- Remove slabs from the
SlabMemoryPool
-
BlazorWebView
controls for WPF & Windows Forms
ده روش امن سازی برنامههای NetCore.
Improper Authentication and Session Management
Most web applications have an authentication module, and we should be careful when writing code for it. We could make mistakes like not removing the authentication cookies after a successful logout. This kind of mistake allows attackers to steal user credentials such as cookies and session values, and may result in attackers being able to access the complete application and cause major negative impacts.
Microsoft has announced that the .NET Core 2.0 will be considered "end of life" and thus no longer supported as of October 1, 2018. .NET Core 2.0 is considered a non-LTS release, and as such Microsoft only commits its support for three months after a successor has been released. In this case, with .NET Core 2.1 having been released May 31, .NET Core 2.0’s end has come.
مفاهیم و اصول OOP
پیاده سازی Remote Validation در Blazor
پیشنیاز: برای اجرای نکات زیر، نیاز به حداقل NET SDK 7.0.101. است و اگر از ویژوال استودیو استفاده میکنید، باید شماره نگارش آن حداقل 17.4.3 باشد؛ در غیراینصورت با خطای «'cannot convert from 'method group' to 'Action» مواجه خواهید شد.
همانطور که در مطلب فوق هم مشاهده کردید، در جهت انجام اعتبارسنجی از راه دور async پس از ورود اطلاعات، تنها رخدادی که در اینجا در اختیار ما قرار میگیرد، رخداد submit (در حالت موفقیت اعتبارسنجی سمت کلاینت و یا تنها submit معمولی) است. بنابراین برای دسترسی به رخدادهای بیشتر EditForm، نیاز است با EditContext آن کار کنیم تا بتوانیم برای مثال به کمک رویداد OnFieldChanged آن، این عملیات async را انجام دهیم. در دات نت 7.0.1، این وضعیت با معرفی modifier جدیدی به نام bind:after@ تغییر کردهاست که در ادامه توضیحات آنرا ملاحظه خواهید کرد.
تعاریف زیر را جهت پیاده سازی یک انقیاد دوطرفه (two-way data-binding) درنظر بگیرید:
<input @bind="username" /> <InputText @bind-Value="Model.Name" />
مشکل! اگر در اینجا نیاز باشد تا در حین ورود اطلاعات، کدی نیز اجرا شود چه باید کرد؟
متاسفانه در این حالت نمیتوانیم رویدادگردان onchange را به صورت دستی، به تعاریف فوق اضافه کنیم و اگر چنین کاری را انجام دهیم، با خطای زیر مواجه خواهیم شد:
RZ10008 The attribute 'onchange' is used two or more times for this element. Attributes must be unique (case-insensitive). The attribute 'onchange' is used by the '@bind' directive attribute.
راه حلهای ممکن انجام اعمال async پس از بروز تغییرات تا پیش از دات نت 7
الف) username متصل را تبدیل به یک خاصیت get و set دار کرده و اکنون در قسمت set آن میتوان عملیات synchronous ای را انجام داد که متاسفانه در این حالت، امکان انجام اعمال async میسر نیست.
ب) چون میخواهیم عملیات async ای را پس از تغییرات انجام دهیم، باید از انقیاد دوطرفه صرفنظر کنیم و مدیریت رویداد onchange را خودمان بهدست بگیریم؛ برای نمونه در مثال زیر میتوان با پیاده سازی async متد CheckUsername به هدف خود رسید؛ اما همانطور که مشاهده میکنید، این عملیات اکنون one-way binding است:
<input value="@username" @onchange="CheckUsername" />
<InputText Value="@Model.Name" ValueExpression="()=>Model.Name" ValueChanged="(string s)=>CheckUsername(s)" /> <ValidationMessage For="() => Model.Name" />
راه حل جدید انجام اعمال async پس از بروز تغییرات در دات نت 7
Blazor در دات نت 7، به همراه یک bind:after modifier@ است که امکان اجرای متدی را (چه همزمان یا غیرهمزمان) پس از بروز تغییرات، میسر میکند و مزیت آن عدم نیاز به بازنویسی متد onchange و از دست دادن انقیاد دوطرفه است:
<input @bind="username" @bind:after="CheckUsername" />
این modifier را حتی میتوان به کنترلهای EditForm نیز اعمال کرد؛ بدون اینکه نیازی به استفاده از راهحلهای پیشین (حالت ج عنوان شده) باشد:
<InputText @bind-Value="Model.Name" @bind-Value:after="CheckUsername" /> <ValidationMessage For="() => Model.Name" />
async Task CheckUsername() { if (!string.IsNullOrWhiteSpace(Model.Name)) { _messageStore?.Clear(EditContext.Field(nameof(UserDto.Name))); var response = await HttpClient.PostAsJsonAsync( UserValidationUrl, new UserDto { Name = Model.Name }); var responseContent = await response.Content.ReadAsStringAsync(); if (string.Equals(responseContent, "false", StringComparison.OrdinalIgnoreCase)) { _messageStore?.Add(EditContext.Field(nameof(UserDto.Name)), $"`{Model.Name}` is in use. Please choose another name."); } EditContext.NotifyValidationStateChanged(); } }
خطای واردکردن(Import) فایل کلید
معماری های رایج برنامه های وب
Most traditional .NET applications are deployed as single units corresponding to an executable or a single web application running within a single IIS appdomain. This approach is the simplest deployment model and serves many internal and smaller public applications very well. However, even given this single unit of deployment, most non-trivial business applications benefit from some logical separation into several layers.