Best place to store view level javascript in an MVC app? - asp.net

For each view I'm creating in my MVC app I will typically have a separate Javascript include that will perform various interactions with the DOM.
With WebForms I used to store the .js file next to the ASPX page, e.g.:
mywebform.aspx
mywebform.aspx.js
What is the best way to store view level javascript includes in MVC? Currently I'm creating them using the following naming convention.
scripts/{controller}/{action}.js
I am then passing a dynamically created path from the action controller to the view and binding in Razor to the shared layout.
#Section viewscript
<script src='#ViewData("ViewScript")'/>
End Section
Can anyone suggest a better way of doing this? I feel with this method I will be spending a lot of time trawling through folders to locate the script. If I can reduce the number of clicks to get from a view to the associated script that would make things more efficient.

Related

Returning custom data along with actionresult from an action method

I am sure many people have had this question but I failed to get any results after searching the web and SO or the search keywords were different.
I am working on a new asp.net mvc web app where I get a plain template returned by the index action method on the controller. Later in the document.ready event handler I build the ui dynamically and append the dom elements to the blank template and this just works fine. My issue is I need 2 server calls here,
1) to get the view from the index action method
2) an ajax call inside the document.ready{} to get the data using which I build the ui.
I was wondering if there is any method using which I could pass back the data from the index action method along with the blank template view and use this data to create the ui inside the document.ready event handler. This will save that one additional hit to the server.
The reason for not using partial views is
1) we have some functionality already developed in jquery and
2) in my org people think making the functionality using razor and partial view will not be as flexible, for example building and raising customevent in js is a great feature that helps to keep the functionality loosely coupled from other features. (please correct if we are wrong)
Edit: I thought an example will explain this better,
Say I need to create a list of users, but the entire list and its functionality like checkboxes selection etc are built by a js module. So along with the blank view i want to pass the "users" object which is a class in my models currently.
Kindly suggest.
You have a couple of options:
1) Server-side rendering:
Putting the necessary data into the model would seem to be the obvious thing to do...that's what MVC models are for.
During the building of the HTML your View code runs - so you can access the model values in Razor code, which you can use to build your view and influence the final HTML. So in this scenario you build your view using Razor, rather than constructing it using JS code. You can of course still use JS to change it after the page has loaded, but it would be downloaded into the browser with the HTML already in the desired starting state.
2) Client-side rendering, but with necessary data pre-populated:
If you'd rather stick with your existing client-side rendering code, you could use Razor to inject some ready-made JSON into the JavaScript, so it's effectively hard-coded into the page when it first runs, rather than having to fetch it from the server separately via AJAX.
For example, if you have some object in C# which holds the data, you can serialise it to a JSON string and then use Razor to write that string into your JS in the correct place.

Custom HtmlHelper for multiple MVC apps

I am currently working on multiple ASP.NET MVC web apps.
All of these web apps have the same navigation bars/menus.
Some of the menu items are app specific, so they can be passed from the respective app.
Some of the menu items are not app-specific, such as whether user is admin or not, based on which I show an admin link on the nav bar. The logic for getting the admin property is available in the business layer.
Is it possible to make this html helper such that I don't have to pass the non-app specific parameters from the respective apps ?
Can I call the business layer from the html helper ?
Is it advisable ?
I want this html helper or any other solution easily distributable...
Thanks
HTML helpers are extension methods on the System.Web.Mvc.HtmlHelper type that return an System.Web.Mvc.MvcHtmlString object. If you want "easily distributable", then you can create a library project with the helper extensions that you need. Then add the project in as a reference on the MVC project.
#using statements can bring in the extensions to the Razor view. The helper object that you bring in through the extension method in the library will give you access to most of the information available to the Razor view at the time the helper is called (with the ViewContext property).
The extensions can be overloaded as much as needed to account for variations in the projects. Common menu options can be added to the library as a static collection that can be accessed by both the MVC project and the extension methods.
update
MVC is set up such that you can do what you want. You have a lot of control. Your helper can include as much code as you need. It's not like you are "breaking the rules". But best practice dictates that you keep your business logic in the controller. By putting that into the helper, which gets called by the Razor view, you are in effect moving the business logic into the Razor view.
HTML Helpers in general are a lightweight way to create HTML code. Thus they are easy to reuse any you can have dozens or hundreds on a single Razor view. That idea gets broken when you move a bunch of business logic into the helper. Then you have a potential of slowing things down if the helper is to be reused a lot.
Good rule of thumb for MVC, if your helper starts getting complicated, create a partial view. I would probably create a model to represent the menu, then create a partial view in the Shared folder that uses that model, then call it from the parent view. I think that would give you more flexibility, and be more in keeping with the MVC best practices.

ASP.NET 2.0 -how do I include files containing server-side code?

I want to be able to load a customized log in page depending on a couple of parameters passed into the querystring.
Each customized login page needs to be able to dynamically display log in errors and possibly have other variables passed in.
Let's say the dynamic login page looks like this (over-simplification here):
<form>
<% if (has_errors) { Response.Write(error_msg); } %>
<input type="text" name="email">
</form>
If the aspx page loads the file like this:
Response.writefile("path/to/custom/page");
the code shows up in the output and doesn't get processed. I have tried other ways to load the file contents (something similar to classic ASP includes) but get the same results every time.
I could have all the custom pages set up as user controls, but I need 100% control over the css, js, and html - and the documentation I read here indicates that I won't have that level of granularity.
link text
PLUS - I'm stuck in a .net 2.0 environment - so .NET MVC is not available to me
Any help/suggestions?
but I need 100% control over the css,
js, and html
You won't get 100% over the page but you will have control inside the User Control instance. Also, many times, you can override these technologies like CSS, from within your control.
In the end because all controls are solified into one big HTML page you will have the same level of control as you would in any single web page with client-side technologies.
You can build a Web UserControl to represent log/in and then include an instance of that control onto any page, in any place, across multiple pages if you wish.
(See the Topics on that MSDN help page about how to create and use it).
Other useful references (these are various angles on the same subject).
Creating a Web user Control in .NET
ASP 101 - User Controls
This should provide a good start to keep looking, if this is the kind of info you think you need.
Internals
The User Control can have its own logic, access the browser querystring, access the page Session, Application, etc. pretty much anything it needs to know for itself to work.
Object Oriented
Additionally, because a User Control is also an object, you can add your own public methods and properties to it through which you can interact to communicate with the control intance on the page (just like you interact with other web controls like Button.Text="click", TextBox.BackColor = System.Drawing.Color.Blue, etc).
Other Options - Dynamic control loading
You might want to consider loading controls dynamically at runtime using the Page.LoadControl(..) method:
Loads a Control object from a file
based on a specified virtual path.
MyControl myControl1 = (MyControl)LoadControl("TempControl_Samples1.cs.ascx");
PlaceHolder1.Controls.Add(myControl1);

ASP.NET equivalent of server side includes

Although the classic ASP method of server-side includes works in ASP.NET, I get the impression it is not the preferred method. How am I "supposed" to be achieving the same effect?
This is how I'm doing it at the moment:
<!-- #include file ="functionlib.aspx" -->
You now have a number of options that provide this effect, but in a different manner.
User Controls (.ascx)
Master Pages (.master)
Server Side Controls (.dll)
Class Libraries (.dll)
App_Code Classes (.cs/.vb)
Each are used for differently to achieve different things. It depends what you're really trying to do. Given the name of your include file, I'd imagine you're trying to include library functions that will be used within the context of your page.
Consequently you'd write a class library that contains the methods and import them into your application/aspx.
If you're looking at templating a page that will do most of the layout work to provide a body for differing content then you'll be interested in Master Pages.
If you're looking at templating controls that can be used in many pages, then you're going to be after User Controls.
If you're looking at templating controls that can be used by many users across many projects, then you'll be looking at Server Side Controls.
If you're looking at a library of classes/methods then you'll develop a class library or use an app_code class which can be JIT compiled the first time it's called. This could at a stretch be considered more like classic ASP, but really it functions more like a class from a class library as a single unit. You can call it from within your codebehind or within <% %> tags in your aspx/ascx code without requiring a reference to a class library.
We don't really use "includes" per se any more, but each of these tools in your toolkit allow you to provide similar concepts for different scenarios. As a developer you will interact with the entire page lifecycle of your web pages differently. ASP.NET is a very different beast than classic ASP. It truly takes a different view/approach and will take some amount of patience to figure out the differences.
How about <% Response.WriteFile("myFile.aspx"); %>?
See: https://support.microsoft.com/en-us/help/306575/how-to-dynamically-include-files-in-asp-net
If you'e using ASP.NET MVC then Html.RenderPartial is your friend here.
http://msdn.microsoft.com/en-us/library/system.web.mvc.html.renderpartialextensions.renderpartial.aspx
A partial view can be implemented as a .ascx or an .aspx and putting the above call in your "primary" page basically says "get the output from this partial view and render it here".
Parial views can make use of the ViewData that your primary view received from the controller.
Sounds like what you need to be looking at is the entire concept of MasterPages.
Unless you are looking at just importing functions and other utilities (not html content). If that is the case (and you are using the code-behind model), you should just be able to include the appropriate file or namespace using the imports command at the top of your .vb page (adjust accordingly for C#).

What is the unit of reusability in .NET MVC apps?

In traditional ASP.NET Web Form applications, UserControls are a great way to encapsulate functionality so that it can be reused. However, UserControls don't fit well into the MVC model. They often make heavy use of ViewState and they blur the seperation of concerns that MVC promotes.
My question is, how do you best bundle a piece of functionality so it can be shared across MVC applications?
As an example, consider a from/to date-selector UserControl that:
allows a user to select two dates, either using a javascript overlay or by typing in day, month and year into seperate fields
can be configured to default to either today and tomorrow's dates or to dates of the developer's choosing
validates the dates that comes back from the user to ensure the from date is before the to date
exposes From and To properties that can be accessed by code-behind
How would I best build something like this in .NET MVC so that I can easily reuse it?
Note that to fully emulate User Control's functionality the MVC component would have to manage the submitted form data and validation - not just the presentation.
In general I would agree that user controls are nice in terms of encapsulating UI stuff, but I don't think too much has really changed in MVC. If I remember right re-using user controls across classic Asp.net projects was a pain and was never really the best way to truly create reusable components. Most UI toolkits that you bought for classic ASP.net didn't give you user controls, they gave you essentially server controls and javascript controls.
In your example, I would probably create or find a jquery (or ur framework of choice) plugin that did what you wanted on the client side. You could also build a C# wrapper around it similar to what Telerik did with some of the jquery UI controls. I do think that the word code-behind and even viewstate will disappear from your vocabulary the more you get into MVC.
If you look at what open source projects are out there for MVC you will get your answer in terms of what you should be doing.
The MVC Contrib app adds a lot of features by creating extension methods and helpers. Their grid control is a typical way to create a reusable component that you could use across projects
Telerik, created some extensions that wrap jquery controls and do asset management.
Finally I think if you look to the future, MVC has areas, which if I interpret it right will give you the ability to break your project apart into multiple smaller projects.
Besides what is already suggested, ASP.NET MVC v2 will have generic templated input controls, see here. You can read how other people do similar techniques, for example, here:
We have
exactly 1 method call for generating a
form element, “Html.InputFor”. As
part of that “InputFor”, it examines
an input specification, that collects
the PropertyInfo, any attributes, the
type, any modifiers called, and
selects an appropriate InputBuilder.
Call InputFor(p => p.Id) and Id is a
GUID? That creates a hidden input
element. Call InputFor(p =>
p.Customer.Address) and Address is a
complex type? That looks for a
partial with the same name of the type
Having considered the helpful answers from others, I will have a go at answering my own question.
It seems to me that the key difficulty with emulating UserControls in MVC is that they crosscut the concerns that MVC aims to seperate. The from/to date selector UserControl in my example incorporates elements of Model, View, Control and interation. UserControls' ability to bundle all this together is exactly the reason that they don't fit well into MVC.
That means that to create a psuedo-UserControl in MVC requires four seperate pieces:
A Model class - in this case an Interval class or similar
A PartialView that knows how to render the Model to HTML
A jQuery script to layer interactivity on top of the PartialView's HTML
A ModelBinder that can deserialise postdata into an instance of the Model class.
The ModelBinder is important because it deals with data coming back from the user. Without it, every Controller that wanted to display a to/from date selector in any of its Views would have to know how to assemble the six postdata fields - and how to cope if they were invalid or some were missing.
Two ways that I can think of. A partial view though this doesn't really transfer well from app to app because you are moving around ascx files. Not a big pain but not my flavour.
I prefer to use WebControls. They are super easy in mvc and all you need to do is reference the library in the project and possibly in your config file and there you go.
I think some of the answers have missed out on the postback functionality of controls. One way you could handle that is to pass any generic information via ViewData when rendering your partial view. That could then post back to its own control, which in turn could redirect to the UrlReferrer.
Its a little messy and use of UrlReferrer poses a security risk. But it is one way around the problem
You can create a jQuery plugin.
As user-controls provided in ASP.NET Webforms, MVC provide a lot of ways to make the controls and code that can be reused in other app.
Using Partials If your partial code have some C# logic and render the html using Razor/aspx code then it's bst to maintain them in razor file.
Write JavaScript Functionality as plugin If you maintain your code and write it as better as it can be used in other app then it would be a huge advantage for you. Next time when you work on other app just open this solution copy it and modify it. Write JavaScript code that can be used as plugin maybe take some more brainstorming.
Write Code As a Separate C# library If some code is too common for every app you make.for example you write a member authentication system or some global function (C#) that are used in every app you made then maintain them in a separate solution so it can be used in other app you made whenever you trying to make a new app in future.

Resources