How to create reusable control in ASP.NET MVC - c#

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

Related

Set a ViewContext property on every partial view of the current ViewResult to disable jquery unobtrusive validation HTML attribute generation

In a project I'm working on, I need to disable jquery unobtrusive validation on some pages and enable it on others. In the current state of the project, the validation is turned on everywhere and has to be disabled on some pages. I know if I have to disable it once I'm in the controller.
I already conditionally import the plug-in's javascript files, so there is no unnecessary download. However, my custom HtmlHelpers that use the default HtmlHelpers still generate HTML attributes that are exclusively used by jquery unobtrusive validation. If I use Html.EnableClientValidation(false); or ViewContext.ClientValidationEnabled = false; on a specific partial view, the attributes are not generated for that specific partial view - exactly what I want. But, because the views are compiled backwards, from the most nested to the main view, this means I would need to set use the Html.EnableClientValidation or ViewContext.ClientValidationEnabled in almost every view, which is not an option.. Correction: I need tried using Html.EnableClientValidation() in the layout of the view, which is called last (after the view and partials). If I place the Html.EnableClientValidation() in the view and not the layout, it will be correctly set. I need this to be done before I get to the view, to avoif writing that in every view.
So my question is, how do I get the effect of an in-view ViewContext.ClientValidationEnabled in every view? Could I set ViewContext.ClientValidationEnabled before the view generation, to get it on every page? From what I researched, I would possibly need to derive from the razor engine? Is there no easier solution, perhaps through some ActionFilter or directly from a controller?
Found it: setting HtmlHelper.ClientValidationEnabled = false; in a controller will set it in all ViewContexts that will be container in the ViewResult or PartialViewResult.
Source

Partial Pages in ASP.NET Core 2.0

TL; DR Are "partial Pages" possible in ASP.NET Core 2.0? If so, why am I getting the error described below?
I've been messing with the new Razor Page feature of ASP.NET 2.0 and having some trouble with partials. The documentation linked above refers to "partials" in several places, but only to the extent of saying mystical things like "The layouts, templates, and partials you're using with MVC controllers and conventional Razor views just work." Do they mean partial Views, like what we're used to, or some new kind of partial Page also? They show that files with the conventional Partial suffix in the name can be placed in the Pages/ folder, but the files that they mention (e.g., _ValidationScriptsPartial.cshtml) don't have the #page declaration. If "partial Pages" are indeed a new thing, then I would expect the following minimal scenario to work:
A Page file named Derp.cshtml:
#page
#namespace MyApp.Pages
#model DerpModel
<p>Member 1: #Model.Member1</p>
<p>Member 2: #Model.Member2</p>
A class file named Derp.cshtml.cs in the same directory (nested under the first in VS 2017's Solution Explorer), containing the following class:
namespace MyApp.Pages {
public class DerpModel : PageModel {
public void OnGet() {
Member1 = "Derp Member1";
Member2 = "Derp Member2";
}
public string Member1 { get; set; }
public string Member2 { get; set; }
}
}
A second Page file named DerpWrapper.cshtml in the same directory, with the following code:
#page "{id}"
#namespace MyApp.Pages
#model DerpModel
<p>Outer Member 1: #Model.Member1</p>
<p>Outer Member 2: #Model.Member2</p>
#Html.Partial("Derp", Model)
And of course a _ViewImports file that declares #namespace MyApp.Pages
Note that both Razor Pages have the same #model type, and the second Page basically wraps up the first one with a call to Html.Partial() and passes its Model. This should all be pretty standard stuff, but upon navigating to http://localhost:xxx/DerpWrapper, I get a 500 response due to a NullReferenceException with the following stack trace.
MyApp.Pages.Derp_Page.get_Model()
MyApp.Pages.Derp_Page+<ExecuteAsync>d__0.MoveNext() in Derp.cshtml
+
<p>Inner Member1: #Model.Member1</p>
...
MyApp.Pages.DerpWrapper_Page+<ExecuteAsync>d__0.MoveNext() in DerpWrapper.cshtml
+
#Html.Partial("Derp", Model)
...
Why does the "wrapper" Page's Model equal null? Is there no way to define a Razor Page and display it from another Page or View with Html.Partial()?
Razor’s partial views are basically .cshtml views that are transcluded into another view, that is a razor view or a razor page. They are rendered within that view and as such inherit some of the view’s properties, e.g. its ViewData. They however do not have a controller, a page model or some other kind of “code behind” that gives you a way to run code for the partial.
As such, the primary use for partials is to extract common components that do not contain logic on their own into separate and reusable files.
The other kind of reusable components that exist in Razor are view components. View components are similar to partials but they do have an actual class that backs them and that allows you to add your own logic to the view component.
At the moment, view components follow the MVC layout for views, meaning the view component is actually a class and you return a view from its Invoke method which causes the view engine to locate that .cshtml in the Views folder. David Fowler confirmed to me though, that they are working on a Razor page like experience for view components too, so in a later version of ASP.NET Core, you will eventually be able to write a .cshtml view component and add some code-behind to it (just like Razor pages).
Coming back to your question though, at the moment there are two kinds of entry points for an MVC route: An MVC controller, possibly returning a view, and a Razor page. Neither of these can invoke one or the other inside of them though. If you are rendering a view, you can load partials or view components but not other “full” views or Razor pages. And if you’re rending a Razor page, you also can load partials or view components, but still no other “full” views or Razor pages.
So what you want to do is simply not possible because a Razor page is supposed to be an entry point to the route, and while invoking any view as a partial may work (in some situations), you will certainly neither get the controller for that view nor the page model running for it. If you want to invoke something that has complex logic, you should use view components instead.
Answers on Stack overflow remain for ages so it's important that we ensure that they are improved.
To add onto Poke's Answer or rather to correct it. Partial views separate common sections between pages. These sections can include logic. But that logic should not involve any field(variables, or objects) contained or defined within any specific page. They can apply logic though dependency injection... by injecting them into the partial view.

How to go to a View in Shared folder from a View in Home folder in MVC using C#

I am trying to access a PartialView in Shared folder by clicking an Html.ActionLink HelperMethod present on a view in Home Folder as:
#Html.ActionLink("Create New", "~/Views/Shared/_AddBranch.cshtml");
with fail. I dont want to add a new controller to achieve this but I don't mind replacing Html.ActionLink with another tool if I need to. Anyone knows how to do it?
You should not be generating an anchor tag which points to the view file directly without an action method. Ideally you should create an action method throuh which you will render the view.
If you are trying to render some re-usable view. You should use Html.Partial method in your main page
#Html.Partial("~/Views/Shared/_AddBranch.cshtml")
Razor will include the HTML markup for the _AddBranch.cshtml when it renders your main page
If you want to pass a model/viewmodel to the partial, you can use this overload
#Html.Partial("~/Views/Shared/_AddBranch.cshtml",Model.YourModelYouWantToPass)
Assuming YourModelYouWantToPass is a property of the model of your main page and your partial view is strongly typed to the type of YourModelYouWantToPass property.

Comparison between Layout and partial view within Asp.net mvc application

I have an Asp.net Mvc4 application which contains 4 modules. I need to add Layouts view (master page) to my project and i have two choices :
Adding 5 Layouts with no partial view
Adding a unique Layout with 4 partial views
I'd like to know what is the best way between it? Why?
In my opinion its better to use 2nd approach. As we know we nowadays heavily uses jquery and want to change view content without having to load whole page.Main reason is partial views are more lightweight than normal views
Sometimes we need to load a partial view , then we can use jQuery to make an AJAX request and render a Partial View . In order to load a partial view with in a div we need to do like as:
<script type="text/jscript">
$('#divforpartialView').load('/Customer/_myAction');
</script>
And moreover idea behind partial view is it is reusable. You can call action which returns partial view like below
<div> #{Html.RenderAction("_Action","Controller");} </div>

Can I populate a ContentPlaceHolder in a master page from within a Razor Partial View?

I'm using the typical built in view engine in mvc3 (is there a proper name for it?) for views and master pages and it's including a Razor partial view on the .aspx page. In the masterpage, there is a ContentPlaceHolder with an ID of "ScriptContent".
I want to be able to fill that ContentPlaceHolder from within the Razor partial view but I don't think this is possible. Does anyone know if it is possible and how I would go about doing that?
I already tried rendering it in the partial like so, but that didn't work.
#section ScriptContent {
... content ...
}
It would be very difficult, so much so that I'd recommend finding another way :(. I wish it was easier, but these are the complexities of integrating a new view engine into an existing legacy system.
To give you a head start if you really want to try it: You'd probably need to create a custom base class inheriting from WebViewPage for your Razor content pages, override some of the methods (honestly I'm not too familiar with that aspect so you'd need to debug to follow the pipeline) so that instead of treating the Layout property as the path to a Layout page, you treat it as a Master page. Then you'd need to instantiate the master page and somehow convert the Sections (which were transformed into calls to DefineSection by the Razor parser, and should be stored in a Dictionary somewhere on the base class) in to Content controls and stuff them in the Master Page.
If I haven't boggled your mind by this point, you may just be able to pull this off, but to be honest, I'd avoid it.
P.S. We refer to the older view engine as "ASPX", based on its file extension ;).

Categories

Resources