I understand when I create a view, I shouldn't be putting any code in there besides html and the data from the model/controller, which is what I've done so far.
But lets say there is a snipped of dynamically generated html that can be used in multiple views, I'm guessing this would be a partial view that goes in the Shared folder in the project. But since it's a partial view, that has no absolute controller to handle it's propagation of dynamic data (from db), how would I call, and where would I code the propagation of data from the db into the view (or model?), if lets say the partial view was to dynamically render content for table.id=n, etc.
I'm fairly to new and working off a tutorial in .net, trying to figure out how to do this. Anyone know how it's done? Hope the question makes sense.
You can always define a model for the partial.
And you can render the partial from the container view passing a dinamically populated instance of its model:
<!-- index.cshtml -->
<h1>Feed Upload</h1>
<div id="uploader">
#Html.Partial("~/Views/Shared/Controls/_FileUploader.cshtml", new FileUploaderModel() { UploaderClassName = this.Model.UploaderClassName })
</div>
In this simple example I call the partial _FileUploader.cshtml from the index.cshtml using the #Html.Partial() method, passing a new model instance that specifies the UploaderClassName value.
Edit
The this.Model.UploaderClassName refers to the container's model and it is initialized inside the container's controller business. Of course the container's controller can run any data access logic to grab dynamic data from the db and pass them to the partial's model.
Have a look at MSDN, and at this article.
Assuming you are using the razor view engine, you can put an .cshtml file in the App_Code folder with helper functions.
The syntax is like this:
#helper FormatDate(DateTime date)
{
#date.ToShortDateString()
}
You call it like this (assuming the file is Utility.cshtml)
#Utility.FormatDate(Patient.DOB)
Because you can pass parameters to a helper, you can pass any type you need, including complex objects.
I recently published a nuget package to do this very thing. It's called Dynamic MVC.
http://dynamicmvc.com
You can look at the source code on codeplex.
https://dynamicmvc.codeplex.com
The way I did this was to use the ModelMetadata engine built into MVC to allow me get the value for any property in a weakly typed fashion. The ModelMetadata engine originally came from ASP.net Dynamic Data and was ported over to MVC in MVC2. It works great for this kind of situation.
Related
I'm trying to have cleaner views for readability and the ease of modification.
I usually have for each view a couple of variables that represents the action URLs used in it:
#model IndexViewModel
#{
// controllers
string newsControllerName = nameof(NewsController).ToName();
// calls to actions
string removeNewsActionUrl = Url.Action(nameof(NewsController.RemoveNews));
string getNewsActionUrl = Url.Action(nameof(NewsController.GetNews));
string indexActionUrl = Url.Action(nameof(NewsController.Index));
}
So I can use them inside the view's data attributes for ajax calls in JavaScript:
<div id="newsContainer"
data-remove-url="#removeNewsActionUrl"
data-view-url="#getNewsActionUrl">
...
</div>
Then a friend of mine suggested that I shouldn't declare variables in a view because it's a bad practice and why not declare them in the ViewModel of that view in this case the IndexViewModel.
I know that views shouldn't have complex logic and should have the minimum of C# code, but is what I'm doing a bad practice? If so why? and is there a disadvantage or an advantage to have variables declared in the ViewModel of that view for this purpose?
From Microsoft docs views and view model:
Views are responsible for presenting content through the user interface. They use the Razor view engine to embed .NET code in HTML markup. There should be minimal logic within views, and any logic in them should relate to presenting content. If you find the need to perform a great deal of logic in view files in order to display data from a complex model, consider using a View Component, ViewModel, or view template to simplify the view.
I couldn't find anything related to this on this site.
I wouldn't want this stuff in the view model. It's superfluous there as there is nothing to be communicated between model and controller.
I don't see an issue with this - it's minimal logic and it is purely concerned with the view itself. Putting it anywhere else would be polluting another part of the codebase for no good reason.
That said, I don't really see any good reason for the code block - why not just inline it in the HTML attributes?
I have two razor page partial views inside of another view. Both are using the same model.
What I'm doing now after a query is:
// get tour data to list to render in _TourenAngebotenPartial.cshtml
var queryfortourangeboten = from TourAngeboten in _context.TourAngeboten
where TourAngeboten.IdUser == Convert.ToInt32(userid)
select TourAngeboten;
View(await queryfortourangeboten.ToListAsync());
This is working fine. Now I have a similar query creating another list but using the same model.
let's say: List<MTO.TourAngeboten> tourteilgenommenlist = new List<MTO.TourAngeboten>();
How can I set this as the data source for the other partial called _TourenTeilgenommenPartial.cshtml
Is there some parameter I can call with View?
Something maybe like:
View("_TourenTeilgenommenPartial", tourteilgenommenlist);
I'm calling both partials with:
#await Html.PartialAsync("_TourenAngebotenPartial", Model.TourAngeboten)
This eventually was a perfect case for ViewComponents. I found many websites explaining those but for a change the one from microsoft was the best:
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-2.1
I am currently working on an ASP.NET MVC solution and have recently introduced both Knockout (an MVVM JS library) and Wijmo (a set of jQuery UI widgets).
With the introduction of Knockout I also need to have models on the client side, so for this purpose I am serializing the C# ViewModel and attaching it to the view using data-model="#Model.ToJson()". This allows me to retrieve the model from JS and apply some client-side love to everything.
However, knockout needs everything to be observables, so I need to declare a separate client-side ViewModel and map everything from the data-model object. This feels very much like duplicate effort and I'd like to avoid it somehow.
I'm hoping someone has a tool or technique to share that will allow me to render the knockout ViewModel directly from the server. Possible solution could include:
Custom JSON serialization to render the observable view model directly to the output in the data-model attribute.
Automatic client-side transformation (I've heard of ko-autobind, but am not sure if it would be a recommended path to take or how stable/complete it is)
Something I haven't thought of
I'd like the solution to be generic and automatic, as my current approach of typing the observable client-side view models by hand is just too unproductive to be viable.
How are you solving this problem?
According to their tutorials it's just a simple .map function
If this is the ViewModel
function Task(data) {
this.title = ko.observable(data.title);
this.isDone = ko.observable(data.isDone);
}
And this function get's the data from the server, it uses the .map function to inject the server data right into the VM
// Data
var self = this;
self.tasks = ko.observableArray([]);
// Load initial state from server, convert it to Task instances, then populate self.tasks
$.getJSON("/tasks", function(allData) {
var mappedTasks = $.map(allData, function(item) {
return new Task(item)
});
self.tasks(mappedTasks);
});
For ko mapping
http://knockoutjs.com/documentation/plugins-mapping.html
For auto-bind here's an example
https://groups.google.com/forum/#!msg/knockoutjs/IJTx37UXQVw/UTrWdEK1C-oJ
Try this pluggin for visual studio
http://visualstudiogallery.msdn.microsoft.com/32c15a80-1c54-4e96-a83f-7cd57573a5d2
Ok, I'm still getting the hang of asp.net and the MVC framework and converting my knowledge over from classic ASP and VB - so please be gentle.
I've got my first view (/home/details/X) functioning well thanks to previous help pointing me in the right direction, now I need to add data from multiple tables and queries/views to the MVC view (I hate that SQL and MVC both use the word view for different meanings).
I'm not looking for someone to write the answer for me (unless they're feeling really energetic), more so for someone to point me in the right direction of what I should be looking at and reading up on to understand it and do this myself.
My problem
There are multiple datasets which I need to display in this view, and each different data set has a proper PK/FK 1-M relationship established, and the resultant records would need to be looped through.
How I would have done this previously
In my classic ASP days, I would have just defined the SQL query at the head of the page where the data was to be used, with a select statement along the lines of:
SELECT * FROM query_name
WHERE query_uniquecolumnname = Request.QueryString("value")
Once that was done, you'd set the do while query_name NOT BOF/EOF up, then drop in the field names you wanted from that query and it was all done.
How do I acheive this now?
So, fast forwarding from my classic ASP knowledge, how do I acheive the same outcome with MVC?
The tables/views I wish to use are already defined within my data model (and the relationships are showing up in there which I would assume is a plus), I just need to work out how I could call these within the page and use the ID of the record being displayed in the Details view to ensure only related data is displayed.
Thanks in advance
The concept you are looking for is called a ViewModel. Essentially this is a custom class that you write that contains all the data that would be used in your view. So it is responsible for amalgamating all the data from the different tables and exposing it as properties. If you're using a data access layer, this is often as simple as bringing a few entities together. If you're using raw SQL to do it, then you would execute your queries when the properties were accessed.
Then you would make your View inherit from the ViewModel, like so:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.MyViewModel>" %>
Now in your View, you can access all the different properties of your object simply by writing statements like:
<%= Html.TextBox("MyProperty", Model.MyProperty) %>
To construct your view from your controller, create a new instance of your class (MyViewModel), pass it the ID of the details record that you need, and the logic in your class will take care of getting the right data. Then return your view from your controller like normal.
var myDetailsModel = new MyViewModel(detailsID);
return View(myDetailsModel);
I would recommend reading this primer on ASP.NET MVC
http://weblogs.asp.net/scottgu/archive/2009/04/28/free-asp-net-mvc-nerddinner-tutorial-now-in-html.aspx
It covers most basic scenarios you'll need to get up and running.
If however you want to combine multiple resultsets into one, and then return it as a view, you should create a custom object, and map the resultset to it, then you can bind against your custom object in the view.
When I need to display multiple things like this on a web page, I use typically use RenderAction to do it.
RenderAction allows you to use a controller method dedicated to that particular part of the view (a subview, in effect), so you can pass a single data set of strongly-typed data to that "subview".
RenderAction is in the Microsoft.Web.Mvc ("futures") assembly.
If you are new at all of this, I apologize; this is a bit bleeding edge, but you're going to need to know it anyway. Be sure to check out the NerdDinner tutorial first.
http://www.andreas-schlapsi.com/2008/11/01/renderaction-and-subcontrollers-in-aspnet-mvc/
http://davidhayden.com/blog/dave/archive/2009/04/04/...
Because of the confusion between all the info that is out there about mvc from all the preview releases and the one official release I am very confused how to deal with viewusercontrols.
So once and for all, tell me how to implement this example:
I have a list of upcoming events that needs to be displayed on several pages of my website. Therefore I have put a new ViewUserControl (ListEvents.ascx) inside my Views\Shared folder.
I am requesting this ListEvents.ascx to render on my Home/Index view like this:
<p>
Here's a list of events:
<% Html.RenderPartial("ListEvents");%>
</p>
How would I go about passing my model to this viewusercontrol? I know I can do this:
<p>
Here's a list of events:
<% Html.RenderPartial("ListEvents", (new Model.Services.EventService(null)).ListEvents());%>
</p>
But that doesn't seem like a very smart thing to do, creating a new model from inside a view?! Or am I wrong here? I can't even pass any validationstate, hence the null parameter.
So an alternative option is to store this data into the ViewData[] member, but my viewusercontrol is not supposed to be dependant on the ViewData of it's parent!
I'm sure there is a very simple answer to this, please share as I'm done browsing the web for this problem.
Thanks!
Simple Answer:
A viewusercontrol should always receive it's model from the View in which it resides. Working around this, like by adding a codebehind file to a viewusercontrol, would break the MVC pattern.
By default, the same model as the page will be used. If you want to provide a model to each instance of RenderPartial, your situation is probably like rendering several entries in a blog application. You could fetch each model from a collection in your page model and pass it to the user control like this:
foreach (var post in Model.Entries) {
Html.RenderPartial("PostTemplate", post);
}