Failed to load local data with Angular 6 and ASP.NET MVC5 - json

For security reason, we have to stick to ASP.NET MVC5. That's why we have to build the frontend Angular app and use BundleConfig to package and grab everything. For the view, we established a view placeholder for our Angular App.
Yes, I agree that it's ugly. However, it seems it is a best solution for us.
Here is the problem: When I try to load the static files. (e.g. images, json files) we have to grab them from the mvc5 backend.
I tried to move the static files to the angular assets folder, and everything got successfully compiled and copied to the dist folder. However, using relative path, Angular cannot recognize them.
Here is the error:
As you may know that the root of our angular app is: http://localhost:1220/client
and the absolute json file location is: 'http://localhost:1220/client/dist/assets/data/UiData.json'
This is my Angular service:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs/observable';
#Injectable()
export class LocalDataService {
private staticDataURL = '../../../assets/data/UiData.json';
// private staticDataURL = 'assets/data/UiData.json';
constructor(private http: HttpClient) { }
public getJSON(): Observable<any> {
return this.http.get(this.staticDataURL);
}
}
both path '../../../assets/data/UiData.json' and 'assets/data/UiData.json' won't work for this case, because the server won't recognize the frontend Angular App.
This is the BundleConfig from our MVC5 backend:
public class BundleConfig
{
// For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/script/bundle").Include("~/Scripts/dist/bundle.js"));
bundles.Add(new StyleBundle("~/style/main").Include("~/Scripts/dist/style.css", new CssRewriteUrlTransform()));
// Angular build artifacts
bundles.Add(new ScriptBundle("~/script/report-bundle").Include(
"~/client/dist/runtime.*",
"~/client/dist/polyfills.*",
"~/client/dist/scripts.*",
"~/client/dist/main.*"
));
bundles.Add(new StyleBundle("~/style/report-style")
.Include(
"~/client/dist/styles.*",
new CssRewriteUrlTransform()
));
}
}
Is there any way to load the local json file using relative path in this case?
Thanks in advance!

We have a very similar environment (for security reasons also).
I'm hoping I can help answer your question by explaining what I 'think' would be the standard way to handle this...
I think the main thing is to just know / decide on a folder to treat as your "web root folder".
In older versions of MVC, it was the /Content folder.
In asp.net core versions, it is the /wwwroot folder.
And then put all of your scripts and assets in that folder.. As long as they are all relative to each other it should work..
So basically, you'll want to edit your output dir of your angular-cli to output your angular app to something like
/Content/js/dist/your files
All of your assets will be in something like
/Content/images/your images
and
/Content/static/your static files
something like that.
in other words, you'll put all your assets in that "web root folder" and also make sure to output your /dist folder to that same folder.
hope that helps!

Related

Proper way to include lists and other external data inside a TypeScript React App

I created a React App using the create-react-app npm package. Everything works fine, however I'm not sure how to handle external files.
I created a POC that holds a json object of the entries for a select field. I can import the object and it works properly. However, I'm used to having files like this available on the server so that they can be edited without having to re-build the program.
I converted the file to a .json and I'm able to import it without a problem. However, if I try to move it to the "public" folder, I'm no longer able to import it. If it remains within the src folder it gets included within the bundle and I'm not able to edit it directly.
Is including the file within the bundle the standard way of handling data that can change (whether by requiring update or i18n)??? If not, how do I go about configuring the app to allow me to import it from the public folder once it's deployed?
This should work:
Add data.json to public directory and use fetch in componentDidMount
componentDidMount() {
fetch('data.json').then(data => {
data.json().then(response => {
console.log(response)
this.setState({ data }); // you can set data to state
});
})
}
content of data.json
{
"data": "some data"
}
If you are trying to use some external data e.g. from server, you should not import it like any other files (i.e. import a.js from './a') you should make HTTP request in order to retrieve these data

How can I establish a plugin ecosystem using ES6 modules?

I want to publish a JS library and let anyone develop plugins for the library.
For example, here's a library I publish:
// awesome-lib.js
export class Library {
registerPlugin(plugin) {
...
}
}
export class PluginBase {
...
}
And a plugin implemented by other developer:
// third-party-plugin.js
import {PluginBase} from './awesome-lib';
export default MyPlugin extends PluginBase {
...
}
And the end-user's code would be something like this:
import {Library} from './awesome-lib';
import MyPlugin from './third-party-plugin';
const lib = new Library();
lib.registerPlugin(new MyPlugin());
However, there's a restriction that the end-user needs to deploy the awesome-lib.js and third-party-plugin in the same directory because the latter imports PluginBase from the awesome-lib.js in the same directory.
In Node.js, this kind of plugin is easy because its module discovery is managed by npm. But in browsers, things get difficult as its module discovery only relies on relative/absolute paths.
Is there any solution for this?

Moving Sitemesh3.xml to a different folder

I'm practicing web programming by using Spring 3.1, Hibernate and SiteMesh3.
I want to move 'sitemesh3.xml' file to other directory as WEB-INF/spring/ (not in WEB-INF directly). I've tried it, but sitemesh didn't work. Is it possible to move it? If it is, what properties, if any, should I add on other files like web.xml?
(I've read http://wiki.sitemesh.org/wiki/display/sitemesh3/Configuring+SiteMesh+3, which says "The configuration file should live in /WEB-INF/sitemesh3.xml in your web-application.")
Consider using java config, you can get rid of xml configuration totally.
Follow Sitemesh Java Config
Create a filter like this and register it in your web.xml or in java configuration file.
#WebFilter(urlPatterns = "/*")
public class ConfiguredSiteMeshFilter extends ConfigurableSiteMeshFilter {
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
builder.addDecoratorPath("/*", "/WEB-INF/decorators/defaultDecorator.jsp");
}
}

Why are my ServiceStack.Razor pages not refreshing until I rebuild my app?

I've got an API project hosted in ServiceStack (3.9), and I've added a /docs folder containing two Razor files, _layout.cshtml and default.cshtml
I have configured no caching; my AppHost class looks like this:
public class AppHost : AppHostBase {
public AppHost()
: base("My API", typeof(UserService).Assembly, typeof(GetUserDto).Assembly) {
}
public override void Configure(Container container) {
ServiceExceptionHandler +=
(req, request, exception) => {
Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
return DtoUtils.HandleException(this, request, exception);
};
JsConfig.EmitCamelCaseNames = true;
Plugins.Add(new RazorFormat());
Plugins.Add(new SwaggerFeature());
}
public static void Start() {
new AppHost().Init();
}
}
My Razor pages are working fine - going to localhost/api/docs shows the default page and uses the supplied layout - but if I make a change to the Razor code, I need to recompile the app before it's visible in a browser.
My understanding was that ServiceStack views worked like ASP.NET MVC views - they're interpreted at request time, and any changes to the view code show up immediately, and if you want to cache your rendered views you'll need to configure that explicitly. Have I missed a config setting, or is there something else I need to do to get ServiceStack pages to recompile without needing to rebuild the project?
You need to set the AppHost config to debug mode:
SetConfig(new EndpointHostConfig {
DebugMode = true,
});
For performance reasons changes are only monitored for in Debug mode. See here for more information.
Automatic reload of modified views, layout templates and partials (in Debug mode)
The best way to avoid the Start-Up penalty is to avoid having to restart the AppDomain in the first place. So in Debug Mode we'll also do this where a background file system watcher monitors all pages, partials and Layout templates for modifications and recompiles and auto-reloads them on the fly, all-ready to deliever instant response time once the page is requested.

using System.Web.Optimization can I mix css and .less files in the same bundle?

It does not look like this is possible because LessTransform will be applied only once all the files have been merged and minified.
public class LessTransform : IBundleTransform
{
public void Process(BundleContext context, BundleResponse response)
{
response.Content = LessWeb.Parse(response.Content, (DotlessConfiguration) ConfigurationManager.GetSection("dotless"));
response.ContentType = "text/css";
}
}
Is there a way to preprocess the less files in some way at Bundling time?
I recently had the same needs and wrote a blog post about the solution that I finally came up with. Here
This can be done relatively easy with a nuget package/some web.config changes (detailed after the package installs so excluding here)/a new transformer in your bundling config.