Injecting dependencies to Knockout component via Razor - asp.net-mvc

Is the following snippet a good practice when using Knockout components + Asp.Net MVC? Any drawbacks I am maybe missing?
Is basically injecting part of the ko component dependencies (mainly initial data) by using Razor server side rendering...
Code snippet:
<my-component params="{
foo: '#Model.FooProperty',
bar: '#Model.BarProperty',
baz: #Json.Encode(#Model.SomeArray)
}"> </my-component>
EDIT:
For avoiding the string escape issues pointed by #Quango, I've implemented this helper:
public static stringEscapeString(this HtmlHelper helper, string value)
{
return HttpUtility.JavaScriptStringEncode(value, true);
}
Usage:
<my-component params="{
foo: '#Html.EscapeString(Model.FooString)', ...

We use Knockout in an ASP.NET MVC project at my job, and do consider this bad practise. But the reasons for this might not apply to you. This is something you'll have to judge for yourself
No caching of HTML (since the injected values might change)
No bundling of your HTML with your JavaScript (same as above)
Mixing different solutions for the same problem can be a bad practise, especially in (large) teams. Essentially, you've picked Knockout, so the 'normal' practise would be to acquire any data you need in JavaScript, and bind to it in your view. If this is what you usually do, consider if you really want to create an exception here, just because the data is (supposedly) static. If this is all about saving a few bytes, then just imagine balancing this out to serving ALL your HTML and JavaScript in a minified bundle, that can also be cached on the client.
No way to override the data later, it is essentially 'hard coded' by the server.
Your code becomes less portable. Your Razor syntax essentially couples your frontend to your chosen backend technology. If this is a long term project, consider if there might be a small chance that in a couple years from now, you might decide another backend technology might be a better alternative, and if it really makes sense that you'd have to rewrite half the frontend just to make this possible.
None of these reasons are relevant for ALL projects, so it depends a lot on the context. I've tried to list as many possible disadvantages as I could think of.

Related

Is it wrong to create an HttpContextProvider for use in IHttpModules?

I have this legacy ASP.NET webapp that's mostly been transitioned to MVC. Code testability is generally bad, as it happens a lot to legacy apps: responsibilities are in a jumble, tight coupling prevails, that sort of thing.
I've been refactoring the app for a couple weeks to improve testability, doing my best to abide by SOLID, and I've come to this point where I need to pass HttpContext or HttpResponse and the like to a method in the HttpModule. Now, obviously the HttpModules can grab a copy of the HttpApplication and just pass that everywhere - which is how it is atm - but I would rather not grant access to such a large root object to a dependency.
Because some of our IHttpModules are initialized before the MVC even comes into play, I've had problems with using an IoC container to inject HttpContextBase or HttpResponseBase into constructors of various helpers that the modules use. I thus have to either pass the HttpContextBase to methods of said helpers - which is taxing to use and feels somewhat wrong - or create something like this:
public class HttpContextProvider : IHttpContextProvider {
// ... ctor
public HttpContextBase GetContext() { return HttpContext.Current; }
}
I would then inject an instance implementing IHttpContextProvider into a helper and call .GetContext() on it later as needed.
Intuitively, I feel like I might be doing something wrong, but cannot really get a handle on what it could be. This whole refactoring is complex enough - and the bus factor in the team is low enough - that I'm hesitant to request too much of the lead dev's time for this issue, which could almost be seen as academic from a practical standpoint.
I can suggest different options
try to register this objects in IoC, but to fix the problem (that class is initialized before it's dependences can be resolved) just use Lazy< T>, most IoC support them, check if yours is
Introducing providers as in your example, but I'll suggest it to return not HttpContext (or HttpResponse), but exactly what you need from this classes, it would be easier in tests to mock this behaviour (you maybe even don't need to construct context there at all) and also it will hide all complex stuff of HttpContext that isn't used
The second option will work only if you use this objects in similar way each time - so that you can replace it with 2-3 methods of ISmthProvider. If you use objects always differently maybe it will be better to combine both approaches and extract the most popular usages into some service and in other places path Lazy< HttpContextBase> to constructor
In my opinion it's better not to pass HttpContext/HttpResponse directly as it giving access for too much stuff and later people can make a mess of it (using it without thinking as it's already there) as a result it would be difficult to test and to make refactoring later.

What is the use of Html.BeginForm in MVC3

What is the use of Html.BeginForm in MVC3.
Why do we use it, when we can just add a form tag directly, does this html helper add some capability or does something which cannot be done with a simple form tag.
The Html.BeginForm helper method contains a couple overloads whose intended purpose is to make writing routed forms easier. It is aware of MVC stucture and makes sure its targeting a controller and action. It's just a bit of syntactic sugar over:
<form method="post" action="#Url.Action(...)">
In Microsoft's words:
The ASP.NET MVC framework includes helper methods that provide an easy way to render HTML in a view.
Of course, no one is making you use them. Its just a matter of preference. In fact, in the early days of MVC, many WebForms developers celebrated their new freedom from server controls a-la <asp:TextBox> et al., and insisted on writing everything by hand.
Using the helpers for your form fields comes highly recommended, since they're aware of things like form validation. Html.BeginForm just gives you a consistent way to start and finish your form:
#using(Html.BeginForm())
{
#Html.LabelFor(...)
#Html.EditorFor(...)
}
Html.BeginForm returns an IDisposable object, allowing you to wrap it in the C# using statement. When the using exits, the disposal will call Html.EndForm() automatically for you. Since Html.EndForm returns void it is slightly inconvenient to call from Razor:
#Html.BeginForm()
<formStuff>
#{Html.EndForm();}
A simple #Html.EndForm() will turn in to Write(Html.EndForm()) -> Write(void), ie compile time error.
Of course you can code it by hand, but it does have several advantages, such as:
it returns an object that is disposable, so that you can put it in a using clause and it will close the form tag for you
it computes the URL for the form action
does something which cannot be done with a simple form
At the end every helper method call is converted to pure HTML so there is nothing that Html.BeginForm can do that can't be done by using the <form> tag directly.
Html.BeginForm is purely an helper method.
What's the purpose of having helpers at all? (Rhetorical question) You could type all inputs manually as well, but helpers... well, help you sometimes.
all it does it put tag. Yes, you can do it manually, or you can be a bit more fancy and do this:
#using(Html.BeginForm())
{
}
This will close the form tag for you as well. So if you keep all your inputs inside the curvy brackets, you don't need to worry about remembering closing the form tag.
Excellent question, I wondered about that myself quite a bit.
I could be wrong, but here's my guess (a better man may correct me):
In the early days of MVC, there was no razor.
Switching between C#/VB and html was hard syntax-wise, so there was a push towards minimizing those borders.
When creating forms, it was seen beneficial to create the entire form purely on the C#/VB side, without any intermingling manual html, to just have one border to the surrounding world of html.
And since programmers often copy the style of doing things from somewhere else, the practice of using those helpers has persisted even though their benefit has disappeared with the advent of razor.

Where do you put methods for common web uri paths

We have a pretty common architecture:
Database
Repository Layer
Business Objects
Services Layer - serves DTOs to the client
Web Layer (MVC)
We've got a number of common paths to resources, in particular images and podcasts (Ex. http://media.mysite.com/podcasts/). I want to create a static utility class with properties:
MySite.Utils.ImagePathUri
MySite.Utils.PodcastsPathUri
etc
My question is: Where do you put uri paths? Into which project does this utility class go?
Initially, it seemed a no-brainer: the web layer. It's a web site. I should be able to change the urls of a site without the other layers knowing about it.
Everything was fine, but, . . . then one day one of my services needed to provide a SyndicationFeed type. The SyndicationFeed needs a full URI, not just a partial file name. But the services shouldn't have access to full paths. Or should they?
I've debated with myself several things, but can't come up with a firm position:
Move the paths to the services layer. That tightly couples the web layer to the services layer, but maybe that's ok, since they're pretty tightly coupled to begin with.
Move the paths to the business objects or repos. I don't like this, but if I'm open to putting it into the services layer, I have to at least consider it.
Don't use SyndicationFeed inside of services layer, but use it only in the web layer. Solves the issue, but it seems like SyndicationFeed should belong in a services layer.
Discard SyndicationFeed. Any SyndicationFeed can more easily be created in MVC with a PartialView that generates the appropriate XML without having to mess with the bloated abstractions like ElementExtensions. I like this one, but we're using SyndicationFeed in a number of places, so that one will take the most explaining to do.
Provide a fake uri to the syndication feed in the services layer and then change it in the web layer. Can you say hack?
Put the full path in the database. That sounds ok at first, but then I realize that it breaks as soon as you have a dynamically generated image.
Some other solution that doesn't occur to me.
What are your thoughts? Where do you put utility classes for web resources (images, podcasts, etc)? And if you say "web layer", what's your take on the SyndicationFeed issue?
UPDATE
At the end of the day, I decided to scrap the SyndicationFeed class, which negated the need for including the path to the file in the service and repository layers. However, the problem still comes up elsewhere and using DI and, in particular, an IoC like Ninject makes perfect sense. So does wrapping together these into a common interface.
SyndicationFeed, View engines and why Declarative does Declarative better
I ditched the SyndicationFeed and instead created the XML that I needed using Razor. Not only is it much easier to create, but it's 1000% more readable. I've come around to the opinion that using imperative code (C#, VB, etc.) to create XML is just harder than it ought to be. XML is declarative, not imperative.
Instead, I've now decided that declarative syntax of View Engines (e.g. Razor) is much easier to work with than imperative languages.
I feel your pain. I too had a similar situation that I resolved by passing the uri to my repository layer, from my web layer.
My project uses Ninject for binding, and since I was already passing the connection string to the repository with Ninject, it was a simple matter to pass my path string as well.
My repository then massages the path string and populates the necessary properties in my business object.
Is this proper? I do not know, but it works for now. I am not completely happy with the solution, but I have not yet had a chance attempt an improvemnt.
Would love to hear how others have dealt with this.
Facing a similar situation I felt the best way to approach it was to define a configuration interface that resulted in an object at the top most layer. Each layer in between would refine the interface with more specific properties and operations:
public interface IWebConfiguration
{
string RootImageUri { get; }
}
the service would layer would add the things needed by itself:
public interface IServicesConfiguration
{
string SyndicationFeedUri { get; }
}
public interface IDatabaseConfiguration
{
string ConnectionString { get; }
}
In the end I had the web tier implement the specific object that wired up all of the interfaces. Ugly? Perhaps. I will admit there was calls to isa in there and some casting.
However, I was able to then pass to each layer a strongly typed interface. In my opinion it was better than having a series of calls to get plain old string from a config file. Also, because each property was specific to a layer and the aggregate object was being passed around I only had to load the configuration once.

why is using if-else blocks inside views dreaded? - MVC

What areas get affected by it?
code readability? maintainability? performance? security? any other?
my views have been using something like
if(Model.Showthis) {<div id = "showthis">...</div>} }
and does doing something like the following have security implications? --
<%if (HttpContext.Current.User.Identity.IsAuthenticated && item.Poster.UserName == HttpContext.Current.User.Identity.Name)%>
<%{%>
...
<%}%>
yes I read "if" considered harmful in ASP.NET MVC View (.aspx) files? too, but it didn't exactly specify what areas get affected by it. I mean I wanted to make sure there are no security and performance implications, which the link didn't answer exactly
I think the stigma persists from the transition from ASP to ASP.NET Forms. MVC is a different beast. With MVC3 and Razor it should help break the stigma and allow for more readable, easier to write Views.
That said, Domain and Business logic should never be in your template. But I see no problem, and frequently make use of conditional statements and loops to render UI in my Views.
I don't see an issue with it as long as the branching logic is purely for UI concerns. With that in mind I would change your second if to:
<%if (item.Poster.UserName == Model.CurrentUserName)%>
<%{%>
...
<%}%>
And set your model up so that the CurrentUserName property looks like this:
public string CurrentUserName
{
get
{
return HttpContext.Current.User.Identity.IsAuthenticated
? HttpContext.Current.User.Identity.Name
: String.Empty;
}
}
Or even better if you're going to be checking author against current user a lot in your system, offload that property to a helper class that can be reused from multiple models. Basically I wanted to get the implementation detail of what the current user's name is out of the view.
There's nothing wrong with if else statements in your view template. What you want to avoid is business or model logic in side your view template. If the conditional is directly related to user interface, then it belongs in the view.
Yes, it can be a bit difficult to read because of the mix of HTML and C#, but so long as your view logic is in your view, and your model logic is in your model, you are properly maintaining separation of concerns.
With your second sample; it might make more sense to only have your Poster available to the View if the correct user is logged in in the first place; this seems like more of a Controller thing than a View thing to me.
A lot of people see if statements in the View and cringe, because it reminds them of classic ASP. But the problem with classic ASP was never that there was code and HTML in the same place; it was that there was business logic and presentation logic in the same place.
Edit Also, perhaps duplicate of "if" considered harmful in ASP.NET MVC View (.aspx) files?.
Why are they bad?
As many people have already suggested it's because it can be a warning sign that business logic is leaking into your views which is a bad thing. Or that you are trying to do too much in your view. Often it's easier to setup the necessary data in your controller and just pass everything required (including any computed values) and have your view render it straight out. The flatter and simpler your view model is the better.
I don't think there is anything wrong with using if/else's for the true purpose of conditionally rendering UI. For example, if a user is logged in render this partial if they aren't than render something else.
I think a lot people get taken back and draw a hard and fast 'it's bad practice' because it can easily lead to tag soup. This phenomena has already been highlighted as a carry over from the asp.net webforms engine. Whilst still a good thing to be aware of, it is likely less of an issue with the razor engine as it's much cleaner and requires less syntax to achieve the same thing. The automatic switching in and out of C#/VB code to html and back is very simple with only an # required to re-enter a code block. I don't think this will create tag soup in the same way that angled brackets did <% %>. The amount of noise in the latter was what most people objected to (and rightly so).
Lastly, circumstances depending, if you find you are starting to get a lot of if/else logic in your view sometimes it is cleaner to put that into a HTML helper. I can't find the reference but I remember Rob Connery once saying that if you find yourself starting to write if statements in your view than it's a candidate for a html helper.
Is there performance of security concerns?
I don't think there is going to be any noticable performance differences or security concerns with what you are asking. But considering an authentication check like that is likely to be used in multiple views I would put it into a Html helper.
If-else blocks are not bad specifically. Code in views is bad because you are mixing HTML markup with code. ASP.NET MVC is bad for separating static page design from dynamic UI code. Web Forms is better at separating static and programmatic UI elements.

Inclusion Handling in MVC 2 / MVCContrib

I'd like to improve my page by combining and minifying javascript and CSS files. Since MVCContrib already contains a project called IncludeHandling, I took a look at that which unfortunately left me with unanswered questions:
There is quite a set of interfaces and objects involved in the process. Now I'm using Ninject.Mvc, but it seems that MvcContrib.IncludeHandling is using some additional (home-brewed?) DI? Can I work around this? Has anybody used this and can share some experiences?
Secondly, advice that is often heard is to put static content on different domains so the request does not contain cookies and the like, making it much easier for the server to handle the request. But how can I combine this with automatic inclusion handling - isn't that necessarily served in the same application?
EDIT: Figured that there is really just a single resolve call in the whole thing, i really wonder why they use DI for that... Thinking about a fork there...
Well, MvcContrib.IncludeHandling uses MvcContrib's DependencyResolver to find the necessary components. It's not very well documented (see the sample site for more detail, although in that case uses a custom injector).
For example, MvcContrib.Castle has a WindsorDependencyResolver for that IoC container that you can mimic to use NInject (there may be something if you Google around).
The initialization is quite verbose, but goes like this (container is the Windsor container, in your case, use NInject):
var httpContextProvider = new HttpContextProvider(HttpContext.Current);
var settings = IIncludeHandlingSettings)ConfigurationManager.GetSection("includeHandling");
container.Register(Component.For(typeof(IIncludeReader)).ImplementedBy(typeof(FileSystemIncludeReader)));
container.Register(Component.For(typeof(IIncludeStorage)).ImplementedBy(typeof(StaticIncludeStorage)));
container.Register(Component.For(typeof(IKeyGenerator)).ImplementedBy(typeof(KeyGenerator)));
container.Register(Component.For(typeof(IIncludeHandlingSettings)).Instance(settings));
container.Register(Component.For(typeof(IHttpContextProvider)).Instance(httpContextProvider));
container.Register(Component.For(typeof(IIncludeCombiner)).ImplementedBy(typeof(IncludeCombiner)));
container.Register(Component.For(typeof(IncludeController)).ImplementedBy(typeof(IncludeController)).LifeStyle.Transient);
DependencyResolver.InitializeWith(new WindsorDependencyResolver(Container));
This way you can register all the dependencies that are needed. Beware that you need the includeHandler section in your web config.
<configSections>
<section name="includeHandling" type="MvcContrib.IncludeHandling.Configuration.IncludeHandlingSectionHandler, MvcContrib.IncludeHandling"/>
</configSections>
<includeHandling>
</includeHandling>
I hope this helped.
Check out the Asp.Net Ajax Minifier. http://www.asp.net/ajaxlibrary/ajaxminquickstart.ashx
It ships with a MS Build task that you can setup where on build it will find and minify Css and Js files in your project...
Here is a Unity version of the DependencyResolver setup. I did it as a Unity container extension.
public class ConfigureMvcContrib : UnityContainerExtension
{
protected override void Initialize()
{
var settings = (IIncludeHandlingSettings)ConfigurationManager.GetSection("includeHandling");
Container
.RegisterFactory<IHttpContextProvider>(c => new HttpContextProvider(HttpContext.Current))
.RegisterFactory<IIncludeReader>(c => new FileSystemIncludeReader(c.Resolve<IHttpContextProvider>()))
.RegisterType<IIncludeStorage, StaticIncludeStorage>()
.RegisterType<IKeyGenerator, KeyGenerator>()
.RegisterFactory<IIncludeCombiner, IncludeCombiner>()
.RegisterInstance<IIncludeHandlingSettings>(settings);
DependencyResolver.InitializeWith(new UnityDependencyResolver(Container));
}
}
It is worth noting that the IncludeHandling setup is not ideal for a web cluster setup as is because of the way it does caching. I had to roll my own controller action that took a list of files to combine and minify. I can provide more info if anyone is interested.

Resources