I love Bundling and Minification in ASP.NET MVC 4.5 and use it a lot.
However, one small problem is that our "plugins" are hosted on a cookieless domain, which is in a separate project in my Visual Studio solution.
I'm looking for a solution that'll allow our main site to request a bundled and minified JS file containing any number of our plugins from the cookieless site. Something like:
http://my.cookieless.domain/plugins.js?include=alpha&include=bravo,charlie
So far, the best solution I can find is to use a 3rd party bundling and minification library, which seems like overkill considering ASP.NET has one built in.
Is it possible to manually call ASP.NETs bundling/minification process from a within controller action?
public JavaScriptResult Index(IList<string> include)
{
//bundle and minify JS
}
I came across this in search of something similar, here is the solution:
public ActionResult DynamicJs()
{
// Obviously this will be dynamically generated
string javaScript = new Minifier().MinifyJavaScript("alert('Hello world!');");
//returns minified javaScript
return JavaScript(javaScript);
}
Same goes for CSS. You might want to use:
new Minifier().MinifyStyleSheet(styleSheet, new CssSettings { ColorNames = CssColor.Hex }
The Minifier class is a member of Microsoft.Ajax.Utilities, which you can get from the WebGrease Nuget package.
Related
I have a web app built with ASP.NET 4.6.1 and uses the Razor view engine. Is it possible to execute a command that will render all my template files (.cshtml files) to static HTML?
I need static HTML files for certain steps in my build process and I can't think of how to render all my view files into html.
I was thinking of something like what you are talking about, but my idea was a way to generate JS files (for building PhoneGap apps, for instance). The project was on BitBucket. The controller/view can generate the JS files necessary for executing the app, which was done by going to a URL to render the content, which you can view in the demo app. Any controller in the app marked with a special attribute gets rendered out to a target folder.
I was hoping to invest more into it but didn't get too far. However this was pretty easy to setup so I hope it can give you a starting point. At worse, you can create a process that spawns a browser to target this URL... At best, there is probably a better way to internalize the components to run "out of band."
Not sure if exist a easy solution for that. But if you really need it through the build process I suggest to create a consoleApp and call it from the build.For the console you can use the RazorEngine it compile/parse the razor for you.
I know you can use C# and .NET with Angular 2, but I've only seen it done in the layouts. Can you include C# in the component files? For example, there is a dashboard.component.html file in the Tour of Heroes tutorial on the Angular 2 website. Could you change that to dashboard.component.cshtml and include C#/Razor?
I am 90% sure you can't do this without a hack. Even though they look like a standard HTML file, they are separate as a convenience. They are typically streamed into your JS code on build.
That said, my 10% answer is that you could probably do something that would wrap a server call in a JS nugget so you could keep the actual CHTML server-side. You should be able to bake a script section that calls out like this: ASP.NET MVC rendering partial view with jQuery ajax
Can you give your scenario of why you would want to do this?
Angular 2 (Javascript/Typescript) is client side (though it still uses a transpiler to convert TS to JS.
While cshtml files are compiled through the ASP.NET compiler as they are apart of the declarative resources in ASP.Net structure.
Razor syntax needs an engine that understands what the symbols means the compiler holds references to these so that when it's interpreted it generates the correct code under the hood. However they are dynamically compiled by the ASP.NET runtime.
See more info here: Why isn't a compilation needed when updating cshtml files with .net code?
https://weblogs.asp.net/scottgu/introducing-razor
Can you include C# in (angular 2) component files? The answer is no and why would you want to do that anyway? I use Angular2 and Asp.net MVC together all the time. But it's important, conceptually, to understand a few things:
Let asp.net handle the backend, and let Angular2 handle the front end.
Otherwise don't mix the two (unless you are into Angular Universal in which your ng2 app is pre-rendered on the server, but this is a special topic).
I separate these concerns so completely that, when I am developing, I use the angular-cli within the context of Visual Studio Code, i.e. not one byte of .net is present in the Angular2 development environment.
Now of course your ng2 app is probably going to want to make calls to "the server", i.e. make http calls etc such as the following:
getMeSomeServerData(someVar: string): Promise < IGenericRestResponse > {
let headers = new Headers();
headers.append("Content-Type", "application/json");
let url = this.apiUrl + "getMeSomeServerData";
let post = this.http.post(url, JSON.stringify(someVar), {
headers: headers
}).map(response => response.json());
return post.toPromise();
}
The key thing to notice here is:
this.apiUrl
When I am in development mode I make this refer to my back-end project located at something like http://localhost:1234/ which refers to an asp.net MVC project i am running concurrently in Visual Studio. So the back-end looks something like this:
[HttpPost()]
[Route("getMeSomeServerData")]
public JsonNetResult GetMeSomeServerData(string someVar) {
GenericRestResponse response = new GenericRestResponse();
response.Error = false;
// do somthing
return new JsonNetResult(response);
}
Note: you have to configure your asp.net mvc backend for CORS or cross-origin HTTP requests since your ng2 app is not on your mvc project domain.
Now, if you like, you CAN have your backend service return text, i.e HTML. Which means you can even go so far as to return partial cshtml views, which is just text after all. Then on the front end, your ng2 app can inject the html however you like. This generally defeats the purpose of Angular 2, in my opinion, and your server can become bogged down with rendering views. But it's up to you.
In any case, when you want to deploy your app for production, then you use the the angular-cli command to bundle and optimize your ng2 app ("ng build -prod"). Then copy all the assets in the "prod" folder to your asp.net mvc project (gulp makes this fast and easy). Use ONE razor view and one razor view only to server your webpage. Here is an example of such a view, Home.cshtml:
<!DOCTYPE html>
<html>
<head>
<base href="/">
<script type="text/javascript" src="~/assets/js/styles.bundle.min.js"></script>
</head>
<body>
<app>Loading...</app>
<script type="text/javascript" src="~/assets/js/main.bundle.min.js"></script>
</body>
</html>
And THATS ALL you use razor views for: to serve your initial SPA page view. Just don't forget to change your "apiUrl" in your app to reflect the http calls are going locally.
You can create an Asp.Net MVC application and then add the Angular Libraries and setup your App to use the default Layout and default controller Index action.
Then you can create partial actions and use its URL as a template for the Angular route, ex:
templateUrl: 'YourController/YourPartialAction'
Although this will work, but I don't think it is recommended cause you mixed both MVC and Angular, Angular is supposed to be totally client side and separated from your back end
I'm new to both .NET development and Umbraco due to recently starting a new role where I will be working heavily with both. As usual before starting development I am looking for some shortcut or helper functions that will enable me to work more productively. One set of helper functions I have found I have included below:
public static string DatedContent(this UrlHelper urlHelper, string contentPath)
{
var datedPath = new StringBuilder(contentPath);
datedPath.AppendFormat("{0}m={1}",
contentPath.IndexOf('?') >= 0 ? '&' : '?',
getModifiedDate(contentPath));
return urlHelper.Content(datedPath.ToString());
}
private static string getModifiedDate(string contentPath)
{
return System.IO.File.GetLastWriteTime(HostingEnvironment.MapPath(contentPath)).ToString("yyyyMMddhhmmss");
}
The functions above are called as follows:
<script src="#Url.DatedContent("~/scripts/product.js")"></script>
The aim of these functions is to automatically version Javascript and CSS files to ensure that the latest versions of each JavaScript and CSS file are pulled through by appending a modified date query string to the end of the file references.
My issue here is, and I apologise that this is such a newbie question, but where do I put this function in Umbraco 7 or is this functionality already supported?
From what I have learnt so far, content pages all have some base properties that include date created and date modified however CSS and Script files do not have these properties so I cannot simply reference these object properties using inline Razor code and condense them with the ToString method as I am doing the functions above.
My first thought was that these functions could be included at the top of the template where the razor code block is included automatically but as I am new to .Net I don't know if this is a standard convention.
Any help would be greatly appreciated.
This is not supported out of the box. Except if you use "Client Depencency" framework. This is a sort of "bundels" framework, similar to the Asp.net framework.
What you do is perfectly possible. Umbraco is still .Net.
2 ways of getting this code in your site:
make a new project, build a DLL and drop the DLL in your umbraco website
put your code in App_code and let IIS build it.
Note: you are checking on EVERY request the modifydate. If you have a busy website, you will want to optimize this. E.g. use a partial using #Html.CachedPartial(...) or using a Macro
I'm working on a large scale software which consists of about 300 projects written in C#. The software is working based on a framework and a WinForm based portal for UI.
Our team is working to develop the Web portal framework.
The web portal is going to load and return javascript, cshtml and css files which resides in various dlls. For example:
Carane.Accounting.Web:
VoucherSmartPart.cshtml
VoucherSmartPart.js
Carane.Inventory.Web:
GoodRequest.cshtml
GoodRequest.js
The framework resides in somewhere like Carane.Portal.Web.
As the portal is SPA using HotTowel, I configured Durandal to get html views and javascript viewmodels from a Controller.
The controller to return Javascript files works fine.
The problem is with the ViewController which should be like this:
public class ViewController : ApiController
{
[HttpGet]
public string GetSmartPart(string moduleName, string smartpartName)
{
// some code to retrieve the cshtml file from the dll
// and render the cshtml and return the html in a way
// as Durandal recognize it as a html file.
}
}
Questions:
How to get cshtml files from another project to involve in framework project?
How to render the cshtml and return it as a html.
It's important that the cshtml file should be debug-able via Visual Studio while it's getting rendered.
I make use of the bundling features in MVC4 by calling bundles.EnableDefaultBundles();, this allows me to browse to http://website.com/content/css which outputs a singular file of all the CSS files in the /content directory - great.
The issue is I have the following route which loads a blog post from the DB by title: /post/{anything} and in this case {anything} is css (for arguments sake, I can't change it) so the bundling is getting confused and trying to bundling everything in the post directory, which doesn't exist.
Is there any way to exclude a particular URL format or route from being bundled? I think not calling EnableDefaultBundles() would work but does that mean I would have to create bundles for everything manually?
Are you using an old version of the Optimization package? EnableDefaultBundles was removed prior to 1.0. You can still accomplish the equivalent of that method by adding the equivalent js/css DynamicFolderBundles.