Should I change #Html.Partial to #Html.PartialAsync as Visual Studio suggest? - c#

In my code I have #Html.Partial("_StatusMessage", Model.StatusMessage) but Visual Studio warning me that: Error MVC1000: Use of IHtmlHelper.Partial may result in application deadlocks. Consider using <partial> Tag Helper or IHtmlHelper.PartialAsync.
Should I disable this error or I should really change #Html.Partial to #Html.PartialAsync, and why?

Yes we should,
See below section from their official site
Migrate from an HTML Helper
Consider the following asynchronous HTML Helper example. A collection of products is iterated and displayed. Per the PartialAsync method's first parameter, the _ProductPartial.cshtml partial view is loaded. An instance of the Product model is passed to the partial view for binding.
CSHTML
#foreach (var product in Model.Products)
{
#await Html.PartialAsync("_ProductPartial", product)
}
The following Partial Tag Helper achieves the same asynchronous rendering behavior as the PartialAsync HTML Helper. The model attribute is assigned a Product model instance for binding to the partial view.
CSHTML
#foreach (var product in Model.Products)
{
<partial name="_ProductPartial" model="product" />
}
Copied from
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/built-in/partial-tag-helper?view=aspnetcore-2.1

Starting with ASP.NET Core 2.1 ... use #await Html.PartialAsync() instead of #Html.Partial()

#niico, In response to your comment of
Where does the <partial> tag helper fit into this?
Based on what I've been able to find, from documentation and from github it looks like you're supposed to use #Html.PartialAsync() or <partial name="_Post" /> In Place Of #Html.Partial(). However the <partial name="" /> element doesn't seem to work on my version of .NET CORE which is updated as of today (8/23/18)
Please see:
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/built-in/partial-tag-helper?view=aspnetcore-2.1
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/partial?view=aspnetcore-2.1
https://github.com/IdentityServer/IdentityServer4/pull/2344

I don't know your code but I think this one should anser your question:
When to use #await Html.PartialAsync in a View in MVC 6
As per the ASP.NET MVC documentation on partial views. https://docs.asp.net/en/latest/mvc/views/partial.html
The PartialAsync method is available for partial views containing asynchronous code (although code in views is generally discouraged):
Also the note on the page.
If your views need to execute code, the recommended pattern is to use a view component instead of a partial view.
So you should use Partial and avoid PartialAsync, and if you find yourself with a PartialAsync you should question yourself whether you're doing something wrong, maybe you should be using a ViewComponent instead or move the logic from the view to the controller.

You can try this method for " Warning MVC1000 Use of IHtmlHelper.Partial " in MVC project.
Source link
<partial name="~/Views/Folder/_PartialName.cshtml" />
<partial name="/Views/Folder/_PartialName.cshtml" />

Related

How to divide HTML found in .cshtml files

I've got an ASP.NET Core MVC Web App, and one of my Views has too much HTML, causing it to look messy and difficult to find stuff, is there a way to extract some of the HTML (for example a certain div) to a different .cshtml file that I can then include in the View?
Here is a partial view sample:
Shared/partial1.cshtml:
<h1>partial1</h1>
Test.cshtml:
<partial name="partial1" />
Or:
#await Html.PartialAsync("partial1.cshtml")
result:
You can also use View Component,here is an official doc.

Asp.net core View components model binding

I'm looking for a way to invoke Model binder inside View component. I prefer to use build-in functionality from asp.net core, but this is only available inside controllers, not View Components itself. Any way to resolve that problem?
According to View Components documentation:
View Components don’t use model binding, and only depend on the data you provide when calling into it.
However, you could pass model as an object/parameter into your ViewComponent:
#await Component.InvokeAsync("PriorityList", MyModel)
or
#await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })
What do you want to achieve?
As far as I'm aware, this is not possible. The model binding occurs further up in the framework's lifecycle before the controller action is invoked.
I would be really interested in seeing some code as to why you need to do this to see if there are any other potential solutions that wouldn't involve model binding.
You can even use TagHelper
<vc:my-component model="#(Model)"></vc:my-component>
and inside your ViewComponent
public async Task<IViewComponentResult> InvokeAsync(MyModel model)
This is not present inside the official guide
I solved this in my project by using ASP.NET Core's dependency injection to insert my singleton directly into a Razor view.
The code snippet below uses the SignalR JavaScript library to send a notification to the browser if something comes in while they're watching the screen. When the page first loads though, I want to display the notification count in a CSS "bell" image so I get the count from the "singleton" object registered in Startup.cs. I use the List<Notification> object in my back-end code to add new notifications to the single instance object as well as sending the signal to the browser. DI worked great in this case to solve the model binding need.
Startup.cs
services.AddSingleton<List<Notification>>();
NotificationComponent.cshtml
#using PWVault.Service.Notification //optional as you can specify the full namespace instead below
#inject List<Notification> Notifications //this is my registered Singleton from Startup.cs
<link rel="stylesheet" href="~/css/NotificationBadge.css" />
<div class="notificationContainer">
<div class="notification" data-toggle="modal" data-target="#notificationModal">
</div>
<label hidden="hidden" id="notificationCount">#Notifications.Count</label>
</div>
#*modal window*#
#await Html.PartialAsync("_NotificationDetailModal")
<script src="~/lib/signalr/dist/browser/signalr.js"></script>
<script src="~/js/NotificationHub.js"></script>

Is there a way to integrate Tag Helpers into MVC CodeTemplates?

I have just gotten started with ASP.NET MVC 5 (C#) and have been a little confused by the HTML helpers.
#using (Html.BeginForm("Add", "Song"))
I understand how this can be helpful, but feel that for people who do not know Razor/C#, that this will be a steep learning curve if not properly exposed. I am also aware of the Tag Helpers that are available and like what I see so far.
<form asp-action="Add" asp-controller="Song">
To me, this seems more appropriate, as it means that people who do not understand Razor syntax will be able to more easily read and understand what is happening, as it bears much more similarity to "normal" HTML. That being said, changing each page to use Tag Helpers seems monotonous and unnecessary.
I have recently found the CodeTemplate files, and included them in my project with the intention of adding the Tag Helpers in the template files. However, I soon realized that most Tag Helpers need a specific Controller or whatever to fill out the element attributes. Obviously, this Controller/whatever will change dynamically depending on which Controller/whatever prompted the creation of the View. If I hardcode asp-controller="Song" and then I try to create an Album View from this CodeTemplate, I obviously will have used the wrong controller.
Is there a way to access the dynamic property of whatever Controller, Link, etc called the View? In other words, is there someway of doing this in the CodeTemplate, where This is the Controller/whatever that constructs the View from the modified CodeTemplate?
<form asp-action="This.Action" asp-controller="This.Controller">
Example:
If I had <form asp-action="This.Action" asp-controller="This.Controller"> in my CodeTemplate in all Views, and then created the Views from different Controllers:
Song Controller
Create View - <form asp-action="Add" asp-controller="Song">
Update View - <form asp-action="Edit" asp-controller="Song">
Album Controller
Create View - <form asp-action="Add" asp-controller="Album">
Update View - <form asp-action="Edit" asp-controller="Album">
Is this possible at all? Or am I completely off? Let me know! Thanks!
You can try the solution I found here.
<form asp-controller="#this.ViewContext.RouteData.Values["controller"].ToString())"
asp-action="#this.ViewContext.RouteData.Values["action"].ToString())">

How to create reusable control in ASP.NET MVC

How can/should I create some "custom control" in ASP.NET MVC 3? I have red about partial views, ViewUsersControl, Html.RenderAction, but I still don't know, which way is the proper MVC way for razor views.
If I need to render some ajax component to view, I can imagine to do it by partial view, but what if I want to render section with custom logic?
1) PartialViews
2) Custom Html helpers
3) Child Actions
Update ASP.NET Core:
2) Tag Helpers are preferred way over Custom Html helpers
3) View Components are used instead of Child Actions
You may use
#{Html.RenderPartial("YourCustomView",YourModel);}
For instance, In your Shared folder create a new View and name it "_MyCustomControl"
Then in the code write :
#model YourNameSpace.Models.YourModel
#{
Layout = null;
}
#*Here write your control's markup*#
Then in your Views where you want to use this "control" you add:
#{Html.RenderPartial("_MyCustomControl",new YourModel { args });}
If you get into trouble with RenderPartial check this out
In addition to all the other answers for this post, I can offer you the use of EditorFor and DisplayFor templates. These are useful when you want to easily render or edit a custom type. It'll handle validation nicely (which can get weird when using partials) and you can nest them recursively (again another feature that isn't obviously handy until you need it).
You can also use Html.RenderAction() or Html.Action() to call another controller action within a view and display the results in-line in the page. This is probably the closest to what you need as it allows you to render a partial, include code in the controller and it also allows for the passing of parameters.
Links to:
DisplayFor and EditorFor Templates
Action and RenderAction
As you have mentioned that you can use Partial Views.
Yes you can use Partial Views, which is the most effective and efficient way.
For Ajax rendering you can always use
#using (Ajax.BeginForm("Details", new { id = Model.Post.PostId }, new AjaxOptions
{
Few of the links you would like to see
Rendering partial view in ASP.Net MVC3 Razor using Ajax
Render Partial Views using JQuery in MVC3

MVC3 Layout Page, View, RenderPartial and getting script files into the Header (from the partial view)

So I have a Layout page
<head>
#RenderSection("HeaderLast", required: false)
</head>
A view
#section HeaderLast
{
<script src="#Url.Content("~/Scripts/knockout-1.2.0.js")"
type="text/javascript"></script>
}
<div id="profile-tab">
#{ Html.RenderPartial("_userProfile"); }
</div>
And a Partial view
#section HeaderLast
{
<script type="text/javascript">
alert('test');
</script>
}
<div......
I figured it couldn't be that simple. Is there a proper way to do this out of box or will this always require some kind of mediator and passing stuff around ViewData to manually make the content bubble up to the layout page?
Bounty started: The bounty will be rewarded to the best solution provided for this short coming. Should no answers be provided I will award it to #SLaks for originally answering this question.
You cannot define sections in partial views.
Instead, you can put the Javascript in ViewBag, then emit any Javascript found in ViewBag in the layout page.
#JasCav: If a partial needs its own CSS, it has no good way to get it rendered.
If that's the reason for its use, it could very well be by design.
You don't want to have a separate CSS file x partial/helper. Remember, each separate CSS file means a separate request to get it from the server, thus an additional round-trip that affects time to render your page.
Also you don't want to emit direct CSS to the HTML from the partial/helper. Instead you want it to have appropriate hooks you can use to define all the look in your site's CSS file.
You can use the same hooks you have available for CSS to activate custom JavaScript behaviors for the elements involved When JavaScript is enabled.
Finally it may be the case what you need is not a Partial View, but an extra Layout you use for some pages. With that approach you would have:
A master Layout that gets set automatically on _ViewStart like you probably has now. This defines the sections like in your sample.
A children Layout page. Here you have both the extra html, css, js you need to have for these views. This uses both #RenderBody() and #section SomeSection { } to structure your common extra layout.
Some views that point to the children layout, and others that use the default master layout.
How to get extra data to the children Layout is out of the scope of the question, but you have several options. Like having a common base for your entities; using ViewBag or calling Html.RenderAction to get that shared logic related to shared dynamic elements in the layout.
It looks like there was a similar question on SO - How to render JavaScript into MasterLayout section from partial view?.
Unfortunately, there is no possibility of declaring sections inside Partial Views. That is because RenderPartial ends up rendering totally separate view page. There is a workaround to this, though a bit ugly. But it can look better if using strongly-typed model instead of ViewData.
Basically, you need to keep track of the reference to the view which called RenderPartial and use the DefineSection method on the object passed to push data to that view.
UPDATE: There is also a blog post about dealing with RenderSection you may find useful.
Here is another approach using helper methods and templated delegate
http://blogs.msdn.com/b/marcinon/archive/2010/12/15/razor-nested-layouts-and-redefined-sections.aspx
As a follow up to my question, the JavaScript/CSS combiner/minifier tool Cassette supports this functionality to allow you to compartmentalize your JavaScript and other assets that are required for partials.
I purchased a site license and use this in all of my MVC applications now.

Categories

Resources