the best way to maintain html snippets in ASP.NET MVC to return in ajax calls - ajax

i'm looking for a best practices type answer here. basically i have a very chatty application which will be returning bits of data to the client very often. the bits of data returned eventually will end up being html added dynamically to the dom. so i'm trying to choose between the following 2 ways:
return just json data, create the html on the client side using jquery and possibly jquery templates
return the actual html that is build on the server side
i would like to make the choice that is most easily maintained. that is, i want the best way that will allow me to make updates to the html snippets very often.
i'm actually looking for a way to do #2 using ASP MVC partial views and want the ability to use string formatting. essentially i'm looking to make a call like this:
string sHtml = string.Format(GetNewTradeHtml(), "GOOG", "100", "635.50");
and I want GetNewTradeHtml() to actually get the html from a ASP MVC view instead of a string constant that might look like:
const string cNewTradeHtml = "<li><span>Symbol: {0}</span><span>Qty: {1}</span><span>Price: {2}</span></li>";
the string constants seems to be a popular way to do these kinds of things and i hate maintaining those...
basically i think i'm looking for a way to manage view several view templates that i can call ToString() on and get the raw html and use string formatting on it. and i'm hoping there is a suggested way to solve my particular problem natively in ASP MVC (without some hack). but perhaps (unfortunately) the string constants + string.format is the best way to maintain server side dynamic html...
UPDATE:
here's what i've learned since i've posted this question:
there are LOTS of posts here on SO about rendering a view into a string. a lot of different ways, some work with different versions of MVC some don't. some are cleaner than others, some are pretty heavy... ALL of which are normally some type of solution that require a controller context. so in most cases the solutions work great as responses to requests. but for my case, i need to do it outside of the context of a controller so now i need to either mock the controller or make a bunch of fake objects, neither of which i really want to deal with.
so i've determined that there is actually NO easy way to render a razor partial into its string representation without using a controller in a response. they really need to make an easy way to do this without mocking up controller context and request objects.

What are Views in asp.net mvc? They are just html templates, nothing more. They take model and replace template placeholders with model values. And indeed there's no more natural way to render html in asp.net mvc than using Views.
First, declare your view model
public class NewTradeViewModel
{
public string Symbol { get; set; }
public decimal Quantity { get; set; }
public decimal Price { get; set; }
}
than your controller action
public ViewResult GetNewTrade()
{
NewTradeViewModel model = new NewTradeViewModel;
model.Symbol = "GOOG";
model.Quantity = "100";
model.Price = 635.50m;
// PartialView, as you want just html snippets, not full layouts with master pages, etc
return PartialView("TemplateViewName", model);
}
and the very ordinary view - you may have any number of these, just change controller action to return specific one
#model NewTradeViewModel
<li><span>Symbol: #Model.Symbol</span><span>Qty: #Model.Quantity</span><span>Price: #Model.Price</span></li>

Since you mentioned that your app was "chatty" you should probably consider returning Json and rendering on the client side with a template engine.
This is really a toss up though because it looks like your snippets are pretty small.
If you do go with a sending JSON back and forth, I can recommend jquery templates or mustache
backbone.js can also help you better organize your client side components. It is pretty easy to get up and running with it. By default it works with jquery templates, but you can also plug in other templates if you like.
Here is a simple approach to storing templates in separate files, http://encosia.com/using-external-templates-with-jquery-templates/

ijjo,
Just looked at your question again and notice that you are referring to returning the html partialview as a string. there are loads of references here on SO to this type od function, but below is my version taken from an 'old' mvc app that's still in production. without further ado, it's an extension method that hooks into the controller:
public static class ExtensionMethods
{
public static string RenderPartialToString(this ControllerBase controller, string partialName, object model)
{
var vd = new ViewDataDictionary(controller.ViewData);
var vp = new ViewPage
{
ViewData = vd,
ViewContext = new ViewContext(),
Url = new UrlHelper(controller.ControllerContext.RequestContext)
};
ViewEngineResult result = ViewEngines
.Engines
.FindPartialView(controller.ControllerContext, partialName);
if (result.View == null)
{
throw new InvalidOperationException(
string.Format("The partial view '{0}' could not be found", partialName));
}
var partialPath = ((WebFormView)result.View).ViewPath;
vp.ViewData.Model = model;
Control control = vp.LoadControl(partialPath);
vp.Controls.Add(control);
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
using (var tw = new HtmlTextWriter(sw))
{
vp.RenderControl(tw);
}
}
return sb.ToString();
}
}
usage (as per archil's example above):
public ViewResult GetNewTrade()
{
NewTradeViewModel model = new NewTradeViewModel;
model.Symbol = "GOOG";
model.Quantity = "100";
model.Price = 635.50m;
// PartialView, as you want just html snippets, not full layouts with master pages, etc
return this.RenderPartialToString("TemplateViewName", model);
}
good luck and enjoy...

Related

How do I bypass the limitations of what MVC-CORE controllers can pass to the view?

From what I've read, I'm supposed to be using ViewModels to populate my views in MVC, rather than the model directly. This should allow me to pass not just the contents of the model, but also other information such as login state, etc. to the view instead of using ViewBag or ViewData. I've followed the tutorials and I've had both a model and a viewmodel successfully sent to the view. The original problem I had was that I needed a paginated view, which is simple to do when passing a model alone, but becomes difficult when passing a viewmodel.
With a model of
public class Instructor {
public string forename { get; set; }
public string surname { get; set; }
}
and a viewmodel of
public class InstructorVM {
public Instructor Instructors { get; set; }
public string LoggedIn { get; set; }
}
I can create a paginated list of the instructors using the pure model Instructor but I can't pass InstructorVM to the view and paginate it as there are other properties that aren't required in the pagination LoggedIn cause issues. If I pass InstructorVM.Instructors to the view, I get the pagination, but don't get the LoggedIn and as this is just the model, I may has well have passed that through directly.
An alternative that was suggested was to convert/expand the viewmodel into a list or somesuch which would produce an object like this that gets passed to the view
instructor.forename = "dave", instructor.surname = "smith", LoggedIn="Hello brian"
instructor.forename = "alan", instructor.surname = "jones", LoggedIn="Hello brian"
instructor.forename = "paul", instructor.surname = "barns", LoggedIn="Hello brian"
where the LoggedIn value is repeated in every row and then retrieved in the row using Model[0].LoggedIn
Obviously, this problem is caused because you can only pass one object back from a method, either Instructor, InstructorVM, List<InstructorVM>, etc.
I'm trying to find out the best option to give me pagination (on part of the returned object) from a viewmodel while not replicating everything else in the viewmodel.
One suggestion was to use a JavaScript framework like React/Angular to break up the page into a more MVVM way of doing things, the problem with that being that despite looking for suggestions and reading 1001 "Best JS framework" lists via Google, they all assume I have already learned all of the frameworks and can thus pick the most suitable one from the options available.
When all I want to do is show a string and a paginated list from a viewmodel on a view. At this point I don't care how, I don't care if I have to learn a JS framework or if I can do it just using MVC core, but can someone tell me how to do this thing I could do quite simply in ASP.NET? If it's "use a JS framework" which one?
Thanks
I'm not exactly sure what the difficulty is here, as pagination and using a view model aren't factors that play on one another. Pagination is all about selecting a subset of items from a data store, which happens entirely in your initial query. For example, whereas you might originally have done something like:
var widgets = db.Widgets.ToList();
Instead you would do something like:
var widgets = db.Widgets.Skip((pageNumber - 1) * itemsPerPage).Take(itemsPerPage).ToList();
Using a view model is just a layer on top of this, where you then just map the queried data, no matter what it is onto instances of your view model:
var widgetViewModels = widgets.Select(w => new WidgetViewModel
{
...
});
If you're using a library like PagedList or similar, this behavior may not be immediately obvious, since the default implementation depends on having access to the queryset (in order to do the skip/take logic for you). However, PagedList, for example has StaticPagedList which allows you to create an IPagedList instance with an existing dataset:
var pagedWidgets = new StaticPagedList<WidgetViewModel>(widgetViewModels, pageNumber, itemsPerPage, totalItems);
There, the only part you'd be missing is totalItems, which is going to require an additional count query on the unfiltered queryset.
If you're using a different library, there should be some sort of similar functionality available. You'll just need to confer with the documentation.

Understanding relations between model view and controller

I went through a lot of readings about MVC and what each of these does is more or less clear. What I haven't understood yet is how they relate. I mean, I know about these relationships
but how are they implemented? What happens in an MVC framework?
I also have a few questions:
I read that a view can't be coupled with the controller, in other words it can't have a controller object inside, but then how does it use the proper controller if a view is supposed to trigger something in it?
How can the model update the view if its unique job is to represent data?
Is the business logic inside the controller or the model? I have read conflicting points of view
The most basic explination of MVC would be that you have each of the 3 layers.
Model
This contains your data. i.e database or set of classes.
View
This displays data to the user i.e your HTML page.
Contains controls for user interaction.
Controller
All access to data should go through this layer. i.e load data from your data source(model) and save data to your data source.
Carries out any data manipulation before saving or loading.
This create a separation of concerns theoretically allowing you to change anything in either layer without the other layer knowing or caring making for far more maintainable and readable code.
In practice this can become more complicated depending on how you wish to access data and display it although the basic principles still apply, occasionally meaning that each part of MVC pattern could be made up of smaller parts.
In terms of implementing it a good example would be ASP.Net MVC http://www.asp.net/mvc. the following could be a simple implementation of displaying some data via MVC using C#.
Model (C# class)
public class Person{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Controller
public ActionResult Index(){
return View(new Person() { FirstName = "Person", LastName = "1" });
}
View (Index.cshtml)
#model Person
Full name: #Html.Raw(Model.FirstName + " " + Model.LastName)
This would output onto the web page
Full name : Person 1
Please forgive me for any syntax errors, not tested.
More detailed post: http://www.tutorialspoint.com/design_pattern/mvc_pattern.htm

Yes or no: Should models in MVC contain application logic?

Yesterday I had some discussion with one of our developers regarding MVC, more precisely about the role of the model component in MVC.
In my opinion, a model should just contain properties and almost no functionality so there are as few methods in model classes as possible.
My collegue though believes that models could and should have more than that and offer a lot more functionality.
Here is an example we argued about.
Example 1
Let's say we wanted to create a blog. A blog has articles and tags. Each article can have multiple tags and each tag can belong to multiple articles. So we have a m:n relation here.
In pseudocode it'd probably look something like this:
class Article{
public int id;
public String title;
public String content;
public Tag[] tags;
// Constructor
public void Article(id, title, content, tags){
this.id = id;
this.title = title;
this.content = content;
this.tags = tags;
}
}
class Tag{
public int id;
public String name;
// Constructor
public Tag(id, name){
this.id = id;
this.name = name;
}
}
Now, assume that we're working loose coupled here which means that it could happen that we have an instance of Article which has no Tags yet so we'll use an Ajax call (to our backend which has a database containing all the information) to get the tags that belong to our article.
Here comes the tricky part. I believe that getting the backend data via Ajax+JSON should be the controller's job using a dedicated class which deals with the ajax request using a parser:
class MyController{
private void whatever(articleID){
Article article = (Article) ContentParser.get(articleID, ContentType.ARTICLE);
doSomethingWith(article);
}
}
public abstract class ContentParser{
public static Object get(int id, ContentType type){
String json = AjaxUtil.getContent(id, type.toString()); // Asks the backend to get the article via JSON
Article article = json2Article(json);
// Just in case
Tag[] tags = article.tags;
if (tags == null || tags.length <= 0){
json = AjaxUtil.getContent(article.id, ContentType.TAGS); // Gets all tags for this article from backend via ajax
tags = json2Tags(json);
article.tags = tags;
}
return article;
}
// Does funky magic and parses the JSON string. Then creates a new instance of Article
public static Article json2Article(String json){
/*
...
*/
return new Article(id, title, content, tags);
}
// Does funky magic and parses the JSON string. Then creates a new instance of Tag
public static Tag[] json2Tags(String json){
/*
...
*/
return tags;
}
}
Example 2
My collegue believes that this breaks with the idea of MVC, he suggests that the model should take care about this:
class Blog{
public int id;
public String title;
public Article[] articles;
// Constructor
public Blog(id, title, articles){
this.id = id;
this.title = title;
this.articles = articles;
}
public void getArticles(){
if (articles == null || articles.length <= 0){
String json = AjaxUtil.getContent(id, ContentType.ARTICLE); // Gets all articles for this blog from backend via ajax
articles = json2Articles(json);
}
return articles;
}
private Article[] json2Articles(String json){
/*
...
*/
return articles;
}
}
class Article{
public int id;
public String title;
public String content;
public Tag[] tags;
// Constructor
public Article(id, title, content, tags){
this.title = title;
this.content = content;
this.tags = tags;
}
public Tag[] getTags(){
if (tags == null || tags.length <= 0){
String json = AjaxUtil.getContent(id, ContentType.TAGS); // Gets all tags for this article from backend via ajax
tags = json2Tags;
}
return tags;
}
// Does funky magic and parses the JSON string. Then creates a new instance of Tag
private Tag[] json2Tags(String json){
/*
...
*/
return tags;
}
}
And outside of the model you'd do: blog.getArticles(); or article.getTags(); to get the tags without bothering with the ajax call.
However, as handy as this might be I believe that this approach breaks with MVC because at the end of the day all models will be full of methods that do various funky stuff and the controller and helper classes do almost nothing.
In my understanding of MVC, models should only contain properties and a minimum of "helper methods" inside. For example a model "Article" could offer a method getNumOfTags() but it shouldn't do any Ajax calls on its own.
So, which approach is correct?
Generally I try to keep controllers simple in terms of logic too. If business logic is required, it will go up to 'service layer' classes to handle it. This also saves repeating any code/logic too, which ultimately makes the whole project more maintainable if business logic was to change. I just keep models purely as entity objects.
I think the answer above sums it up nicely though, it is easy to over engineer a project based on design patterns: Go with whatever works for you and is most maintainable/efficient.
You should stop treating "model" in MVC like some class. Model is not a class or object. Model is a layer (in modern MVC, there has been some evolutions since the inception of concept). What people tend to call "models" are actually domain object (I blame Rails for this mass-stupidity).
The application logic (interaction between domain logic structures and storage abstraction) should be a part of model layer. To be more precise: it should be inside the Services.
The interaction between presentation layer (controllers, views, layouts, templates) and model layer should happen only through those services.
Application has no place in controllers. Controllers are structures of presentation layer, and they are responsible for handling user input. Please do not expoqbse deomain objects to it.
Correct? Either. They both compile, don't they?
Handy tricks are nice, why not use them were you can? That being said, as you've pointed out, you may get bloated models if you put all sorts of logic in them. Likewise, though, you can get bloated controllers when they do massive amounts in each action. There are ways to abstract elements out of either, if that's necessary too.
At the end of the day all design patterns are is guidelines. You shouldn't blindly follow any rule, just because someone else said it. Do what works for you, what you think gives clean, extensible code and hits whatever metrics you think make good code.
All that being said, for true idealistic MVC I would say that models should not have any external actions, they're data representations, nothing more. But feel free to disagree :-)
Your suggestion about the modules (without any business logic inside) sounds more like you talk about Value Objects. The suggestion of your college sounds more like Domain Objects.
In my opinion the concept which will be used depends on the framework which is used (that's the practical view, the more philosophical one is bellow). If framework is used it usually sets rules about how you should implement each component.
For example we can look at different MVC frameworks. In Flex's Cairngorm framework we have both. VO (Value objects) are primary used for bindings to the view, while the DO (Domain objects) hold the business logic. If we look at ASP.NET's MVC implementation there we have a model which contains at least the data (VO) but also some validation (if required). Let us look at a UI MV* framework - for example Backbone.js. Backbone's documentation says:
Models are the heart of any JavaScript application, containing the
interactive data as well as a large part of the logic surrounding it:
conversions, validations, computed properties, and access control.
If we look into the traditional MVC provided by Smalltalk we see that: "Model: manages the behavior and data of the application domain" so we have some behavior in it, not just plain data.
Let's think practically, if don't have any logic in the Model probably we should put all the application and business logic into the Controller.
Now let's focus on a concrete example. Imagine we have a model which is a Graph. We want to find the shortest path between two nodes in it. A good question is where to put the algorithm which finds the shortest path? It's a kind of business logic, right? If we look at the main benefits of MVC (code reuse, DRY etc.) we can see that if we want to reuse our model in the best possible way we should implement the shortest path inside it. The shortest path algorithm usually depends on the graph inner representation (or at least for best performance of the algorithm) but this representation is encapsulated into the model, unfortunately we cant reuse the full shortest path for matrix representation and list of neighbors so it's not a good idea to put it into the controller.
So as conclusion I can said that it depends on your needs (mostly). The traditional MVC purpose is to be used in the UI (inside GoF
The Model/View/Controller (MVC) triad of classes [first described by Krasner and Pope in >1988] is used to build user interfaces in Smalltalk-80.
)
now we use it in different areas - only UI, for web applications, etc. It cant be used in it's pure form because of that.
But anyway, in my opinion the best separation of concerns can be achieved by isolation of the business logic into the Model and the application logic into the Controller.
In short I believe the Model should just be data that will be sent to your View. It helps drive the MVC paradigm into other aspects of your application.
If you are tring not to break the MVC pattern your data should all be returned as a Business Model to your controller and unpacked into your ViewModel. Request the information server side and then send everything. If you need to make JSon requests then that should either be a Rest Service or calls to a Controller. Having these getTags and getArticles makes it very messy ... if your view is now deciding on which to call ... I cant understand why you dont have that information isnt available upfront. Using static methods is the same approach just a different angle.
I have found it best to have my controller actions call an injected service which does the magic and use the Models within the MVC web application to return the information. This makes things neater and further emphasisis the seperation of concern. Your Controller Actions then become very lean and its clear what they are doing.
I believe starting by treating the Model as completly dumb might go a long way in sorting some of these architectural problems I am seeing from this code.
Yes. It should. You are talking about Domain Driven Design.
https://en.wikipedia.org/wiki/Domain-driven_design
If you feel, you are not doing that then you are doing Anaemic Domain Model Design. that is an Anti Pattern.
I read through an article from Martin Flower on how bad the Anaemic Domain Design is. https://martinfowler.com/bliki/AnemicDomainModel.html

Model binding in controller when form is posted - why to use view model instead of class from domain model?

I'm still reasonably new to ASP.NET MVC 3. I have come across view models and their use for passing data from a controller to the view. In my recent question on model binding two experts suggested that I should use view models for model binding as well.
This is something I haven't come across before. But both guys have assured me that it is best practise. Could someone maybe shed some light on the reasons why view models are more suitable for model binding?
Here is an example situation: I have a simple class in my domain model.
public class TestParent
{
public int TestParentID { get; set; }
public string Name { get; set; }
public string Comment { get; set; }
}
And this is my controller:
public class TestController : Controller
{
private EFDbTestParentRepository testParentRepository = new EFDbTestParentRepository();
private EFDbTestChildRepository testChildRepository = new EFDbTestChildRepository();
public ActionResult ListParents()
{
return View(testParentRepository.TestParents);
}
public ViewResult EditParent(int testParentID)
{
return View(testParentRepository.TestParents.First(tp => tp.TestParentID == testParentID));
}
[HttpPost]
public ActionResult EditParent(TestParent testParent)
{
if (ModelState.IsValid)
{
testParentRepository.SaveTestParent(testParent);
TempData["message"] = string.Format("Changes to test parents have been saved: {0} (ID = {1})",
testParent.Name,
testParent.TestParentID);
return RedirectToAction("ListParents");
}
// something wrong with the data values
return View(testParent);
}
}
So in the third action method which gets invoked when an HTTP POST arrives I used TestParent for model binding. This felt quite convenient because the browser page that generates the HTTP POST request contains input fields for all properties of TestParent. And I actually thought that's the way the templates that Visual Studio provides for CRUD operations work as well.
However the recommendation that I got was that the signature of the third action method should read public ActionResult EditParent(TestParentViewModel viewModel).
It sounds appealing at first, but as your models and view actions get increasingly complex, you start to see the value of using ViewModels for (most) everything, especially input scenarios.
Case 1 - Most web frameworks are susceptible to over-posting. If you are binding straight to your domain model, it is very possible to over-post data and maliciously change something not belonging to the user. I find it cleaner to bind to an input view model than have long string lists of white lists or black lists, although there are some other interesting ways with binding to an interface.
Case 2 - As your input grows in complexity, you'll run into times when you need to submit and validate fields not directly in the domain model ('I Agree' checkboxes, etc)
Case 3 - More of a personal thing, but I find model binding to relational domain objects to be a giant pain at times. Easier to link them up in AutoMapper than deal with MVC's modelbinder for complicated object graphs. MVC's html helpers also work more smoothly against primitive types than deep relational models.
The negatives of using ViewModels is that it isn't very DRY.
So the moral of the story is, binding to domain models can be a viable solution for simple things, but as the complexity increases, it becomes easier to have a separate view model and then map between the two.

How do I display customer specific information avoiding using xslt?

My place of work currently maintains a website for several customers which is written using classic asp. Each customer requires specific parts of the website to be written specifically to them.
For example, customer A requires an Address to be input, displayed and stored in the following format:
Address Line 1
Address Line 2
Address Line 3
Address Line 4
Address Line 5
Postcode
whereas customer B requires the Address to be input, displayed and stored as:
Street
Town
City
Postcode
and so forth...
Therefore, my place of work took the path of storing the data as xml in the database and using xsl (of which I currently know little) to transform the data to html.
So if we require information from the user via a html form, the xml is transformed using xsl. The user then enters the information and submits the data via the form. An asp page is then used to validate the data. This asp page is specific to the xsl page used to display the form. Therefore, we are now in a postion where for each customer we have many xsl pages and many customer specific asp pages (where much of the code is duplicated).
I have been asked to move the site over to asp.net mvc3 and to remove much of the duplication and was wondering what would be the best way to cater for this customer specific field functionality. My preference would be to keep the data stored as xml as the database layer is accessed using com components which I would like to reuse without changing.
I have read that I could keep the xsl pages and develop an xslt view engine to display the html. However, I am not sure how I would validate the data when the user submits the form?
What would be the best way to display customer specific fields if I was to remove the xsl completely? Or would I have to have customer specific views and view models?
Any thoughts would be much appreciated.
If you really want to use MVC's built in validation / model functionality I think your best bet would be to use the XmlSerializer or use DataContracts to develop something that serializes to and from your XML (once its retrieved from the COM objects, so you don't need to re-code those), then you can use those classes as Models for MVC and use the standard data annotations for taking advantage of the richer MVC model functionality and skip the XSL step entirely.
To couple this with a custom specific view, what I typically do is override the default view engine to have one that actually will try names that are more specific to the customer/object and then fallback to a general one.
This view engine would allow you to pass a view to pass a view name (ie. FallbackViewEngine.BuildViewName("General", "Customer Name") and it would look for "General.Customer Name.cshtml" first and then "General.cshtml" as a fallback. This way you can actually use customer specific views in your view folder.
public class FallbackViewEngine : RazorViewEngine
{
const string NameSeparator = "==";
const string FileSeparator = ".";
public static string BuildViewName(string root, params string[] fallbackList)
{
if (string.IsNullOrWhiteSpace(root)) throw new ArgumentNullException("root");
if (fallbackList == null) throw new ArgumentNullException("fallbackList");
var sb = new StringBuilder(root);
foreach (var s in fallbackList)
{
if (string.IsNullOrWhiteSpace(s)) continue;
sb.Append(NameSeparator);
sb.Append(s);
}
return sb.ToString();
}
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
if (string.IsNullOrWhiteSpace(viewName)) throw new ArgumentNullException("viewName");
var names = viewName.Split(new string[] {NameSeparator}, StringSplitOptions.None);
var searched = new List<string>();
//iterate from specific to general
for (var i = names.Length; i >= 1; i--)
{
var result = base.FindView(controllerContext, string.Join(FileSeparator, names, 0, i), masterName, useCache);
if (result.View != null)
{
return result;
}
else
{
searched.AddRange(result.SearchedLocations);
}
}
return new ViewEngineResult(searched);
}
}

Resources