I am trying to render formatted JSON as HTML using Razor Templates.
I am currently trying to do it like this:
<div>
<pre>
#JsonHelper.SerializeObject(item.AttributeValue, new Newtonsoft.Json.JsonSerializerSettings() {
Formatting = Newtonsoft.Json.Formatting.Indented })
</pre>
</div>
But once it gets to the browser, it is all on one line and looks something like this:
"{\"FieldA\":[{\"FieldAName\":\"start\",\"startValue\":\"startValue2\"},{\"FieldB\":\"FieldBsub\",\"FieldBValue\":\"SomeField\",\"Options\":[{\"ANumber\":1,\"Option\":\"LOL\"},{\"ANumber2\":2,\"Option\":\"LMAO\"},{\"ANumber3\":3,\"Option\":\"OTHER\"},{\"ANumber\":4,\"Option\":\"ROFL\"},{\"ANumber\":5,\"Option\":\"ROFL\"}]}],\"Choice\":\"yes\",\"fieldC\":\"yes\"}"
I am assuming the backslashes should be breaks that should be formatting it?
I am new to C# and I am pretty sure there is something wrong with the JSonHelper method? Maybe it is already a string?
Anyways I would like it to display like a formatted JSON in the browser view like this:
Just an example:
[
{
"_id": "5deeea2ed84c28fb633ecac8",
"index": 0,
"guid": "accc7f31-bfc7-4a42-9d76-a6f9f71e6f87",
"tags": [
"proident",
"aute",
"pariatur",
"cupidatat",
"officia",
"adipisicing",
"dolor"
],
"friends": [
{
"id": 0,
"name": "Alyson Scott"
},
{
"id": 1,
"name": "Ratliff Castaneda"
},
{
"id": 2,
"name": "Bernice Lester"
}
],
"greeting": "Hello, undefined! You have 6 unread messages.",
"favoriteFruit": "banana"
}
]
I have a string property in my model that I set to a formatted JSON string
public string PortfolioJson { get; set; }
public async Task<IActionResult> OnGetAsync(int? rid) {
PortfolioJson = JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented);
}
Then on the page I just output that. I also use a JS library to pretty print the JSON.
#section Styles {
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/default.min.css" />
}
<div class="row">
<pre>
<code class="json">
#Model.PortfolioJson
</code>
</pre>
</div>
#section Scripts {
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js"></script>
<script>
hljs.initHighlightingOnLoad();
</script>
}
Related
I'm trying to use Angular 6, angular CLI and MV Areas.For POC reasons I've named it Angular The idea was to have an angular app per Area. If this is a bad idea please let me know because maybe the whole concept is And for me it's a pain. This is the first time that I'm configuring it. Below is my example Area has a main controller which looks like this:
public class MainController : BaseController
{
[HttpGet]
public ActionResult Index()
{
return View();
}
}
And my Route config looks like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "mvc",
url: "{controller}/{action}/",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
// This is a catch-all for when no other routes match the request; let the Angular 2 router take care of it...
routes.MapRoute(
name: "default",
url: "{*url}",
defaults: new { controller = "Home", action = "Index" } // The view that bootstraps Angular 2 app
);
//routes.MapRoute(
// name: "Default",
// url: "{controller}/{action}/",
// defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
I have my app folder in the main project directory, aslo files like angular.json and packages.json. I've created this using angular CLI
Below is an angular.josn file:
{
"$schema": "./node_modules/#angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "eagle-app",
"projects": {
"test-app": {
"root": "test-app/",
"sourceRoot": "test-app",
"projectType": "application",
"prefix": "app",
"schematics": {},
"architect": {
"build": {
"builder": "#angular-devkit/build-angular:browser",
"options": {
"outputPath": "eagle-app/dist/test-app",
"index": "Areas/ANGULAR/Views/Main/Index.cshtml",
"main": "eagle-app/test-app/main.ts",
"polyfills": "eagle-app/test-app/polyfills.ts",
"tsConfig": "eagle-app/test-app/tsconfig.app.json",
"assets": [
"test-app/favicon.ico",
"test-app/assets"
],
"styles": [
"eagle-app/test-app/styles.css",
"node_modules/primeicons/primeicons.css",
"node_modules/primeng/resources/themes/nova-light/theme.css",
"node_modules/primeng/resources/primeng.min.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "eagle-app/test-app/environments/environment.ts",
"with": "eagle-app/test-app/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true
}
}
},
"serve": {
"builder": "#angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "test-app:build"
},
"configurations": {
"production": {
"browserTarget": "test-app:build:production"
}
}
},
"extract-i18n": {
"builder": "#angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "test-app:build"
}
},
"test": {
"builder": "#angular-devkit/build-angular:karma",
"options": {
"main": "eagle-app/test-app/test.ts",
"polyfills": "eagle-app/test-app/polyfills.ts",
"tsConfig": "eagle-app/test-app/tsconfig.spec.json",
"karmaConfig": "eagle-app/test-app/karma.conf.js",
"styles": [
"eagle-app/test-app/styles.css",
"node_modules/primeicons/primeicons.css",
"node_modules/primeng/resources/themes/nova-light/theme.css",
"node_modules/primeng/resources/primeng.min.css"
],
"scripts": [],
"assets": [
"test-app/favicon.ico",
"test-app/assets"
]
}
},
"lint": {
"builder": "#angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"eagle-app/test-app/tsconfig.app.json",
"eagle-app/test-app/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"test-app-e2e": {
"root": "test-app-e2e/",
"projectType": "application",
"architect": {
"e2e": {
"builder": "#angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "test-app-e2e/protractor.conf.js",
"devServerTarget": "test-app:serve"
},
"configurations": {
"production": {
"devServerTarget": "test-app:serve:production"
}
}
},
"lint": {
"builder": "#angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "test-app-e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**"
]
}
}
}
}
}
}
My Index.cshtml from the Area looks like this:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>TestApp</title>
<base href="/Areas/ANGULAR/Main/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<test-app>
</test-app>
#section scripts {
#Scripts.Render("~/Content/angular-ui")
}
</body>
</html>
As you can see I have an routingcomponent which looks like this:
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { Sub1Component } from "./submodule1/sub1.component"
import { Sub2Component } from "./submodule2/sub2.component"
import { AppComponent } from "./app.component";
const routes: Routes = [
{ path: 'Sub1', component: Sub1Component },
{ path: 'Sub2', component: Sub2Component },
{
path: '',
redirectTo: '/Sub1',
pathMatch: 'full'
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
I'm injecting this to my app.component which a loop that creates buttons for submodules like defined above and the view for it is in shared foler. The problem is I'm getting error like below. And I can't get seem to have the default route for sub1 to be loaded.
ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'ANGULAR/Main'
Error: Cannot match any routes. URL Segment: 'ANGULAR/Main'
at ApplyRedirects.push.../node_modules/#angular/router/fesm5/router.js.ApplyRedirects.noMatchError (router.js:1382)
at CatchSubscriber.selector (router.js:1363)
at CatchSubscriber.push.../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchSubscriber.error (catchError.js:34)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61)
at TapSubscriber.push.../node_modules/rxjs/_esm5/internal/operators/tap.js.TapSubscriber._error (tap.js:61)
at ApplyRedirects.push.../node_modules/#angular/router/fesm5/router.js.ApplyRedirects.noMatchError (router.js:1382)
at CatchSubscriber.selector (router.js:1363)
at CatchSubscriber.push.../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchSubscriber.error (catchError.js:34)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:83)
at MapSubscriber.push.../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:61)
at TapSubscriber.push.../node_modules/rxjs/_esm5/internal/operators/tap.js.TapSubscriber._error (tap.js:61)
at resolvePromise (zone.js:814)
at resolvePromise (zone.js:771)
at zone.js:873
at ZoneDelegate.push.../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:3815)
at ZoneDelegate.push.../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
at Zone.push.../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
at drainMicroTaskQueue (zone.js:595)
Anyway I have also a general question is the concept of having seperate apps for an Area is ok? Or maybe some of you have any experience with angular CLI, MVC5 Areas and Angular6? How it should be done. Thanks for you patience and help in advance. Below also are print screens how I have my project structured
Ok with a help of a friend in my team we've managed to solve the issue! The thing is in our MVC app we have also a angularjs (1.x) app and we've noticed that we have hash based urls. That lead us to finding the answer, that in our app module we should import this:
{ provide: LocationStrategy, useClass: HashLocationStrategy }
which get's imported from:
import { LocationStrategy, HashLocationStrategy } from '#angular/common';
in the this looks like this:
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
, BrowserAnimationsModule
, HttpClientModule
, FormsModule
, SharedModule
, AppRoutingModule
],
providers: { provide: LocationStrategy, useClass: HashLocationStrategy }],
bootstrap: [AppComponent]
})
Also we had to delele the html part because we had sort of html in html. That his instead of having this:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>TestApp</title>
<base href="/Areas/ANGULAR/Main/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<test-app>
</test-app>
#section scripts {
#Scripts.Render("~/Content/angular-ui")
}
</body>
We should have only this:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#Styles.Render("~/Content/prime-ng-css")
<div id="test-app">
<test-app>
</test-app>
</div>
#section scripts {
#Scripts.Render("~/Content/mMonitor-ui")
}
This was the solustion for the problem i this specific case and config that we have
I am trying to show my data after json Deserialization on the web.Every data working perfectly except the Images. It shows only image sign on the web but now the actual images.My Code for controller class in where I deserialized Json object is as follows-
public ActionResult PlaceInformation(City objCityModel)
{
string name = objCityModel.Name;
ViewBag.Title = name;
var ReadJson = System.IO.File.ReadAllText(Server.MapPath(#"~/App_Data/" + name + ".json"));
RootObject json = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<RootObject>(ReadJson);
List<Poi> mycities = new List<Poi>();
foreach (var item in json.poi)
{
Poi obj = new Poi()
{
Name = item.Name,
Shorttext = item.Shorttext,
GeoCoordinates = item.GeoCoordinates,
Images = item.Images,
};
mycities.Add(obj);
}
ViewBag.Cities = mycities;
return View();
}
Now in the view class I want to show every item from this json.But I am having error for images which I mentioned beside code. The error is:
An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately. Parser Error Message: Unexpected "foreach" keyword after "#" character. Once inside code, you do not need to prefix constructs like "foreach" with "#"
My code is -
#model CallListService.Models.City
#{
Layout = null;
}
#{
ViewBag.Title1 = "Show Data";
}
#foreach (var item in ViewBag.Cities)
{
<h2>#item.Name</h2>
<p>#item.Shorttext</p>
<p>#item.GeoCoordinates.Longitude</p>
<p>#item.GeoCoordinates.Latitude</p>
#foreach (var image in item.Images) //Parser Error
{
<img src=#image >
}
}
Again if I only write in this way it works but image is not shown, only img sign is shown.
<img src=#item.Images>
I am not finding any solution for this.
This is screenshot of web page
SourceCode:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>PlaceInformation</title>
</head>
<body>
<div>
<h2>Nordertor</h2>
<p>The Nordertor is an old town gate in Flensburg, Germany, which was built around 1595. Today the landmark is used as a symbol for Flensburg.</p>
<p>9.43004861</p>
<p>54.79541778</p>
<img src="System.Collections.Generic.List`1[System.String]" />
<h2>Naval Academy M�rwik</h2>
<p>9.45944444</p>
<p>54.815</p>
<img src="System.Collections.Generic.List`1[System.String]" />
<h2>Flensburg Firth</h2>
</p>
<p>9.42901993</p>
<p>54.7959404</p>
<img src="System.Collections.Generic.List`1[System.String]" />
</div>
</body>
</html>
I am using following json file to get all data
{
"poi":[
{
"Name": "Nordertor",
"Shorttext": "The Nordertor is an old tows used as a symbol for Flensburg.",
"GeoCoordinates": {
"Longitude": 9.43004861,
"Latitude": 54.79541778
},
"Images": [
"https://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Nordertor_im_Schnee_%28Flensburg%2C_Januar_2014%29.JPG/266px-Nordertor_im_Schnee_%28Flensburg%2C_Januar_2014%29.JPG"
]
},
{
"Name": "Naval Academy Mürwik",
"Shorttext": "The Naval Academy Mürwik is the main training e..",
"GeoCoordinates": {
"Longitude": 9.45944444,
"Latitude": 54.815
},
"Images": [
"https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/MSM-hauptgebaeude.jpg/400px-MSM-hauptgebaeude.jpg"
]
},
{
"Name": "Flensburg Firth",
"Shorttext": "Flensburg Firth or Flensborg Fjordg and the villages Munkbrarup, Langballig, Westerholz, Quern, Steinberg, Niesgrau, Gelting, and Nieby.\n\n",
"GeoCoordinates": {
"Longitude": 9.42901993,
"Latitude": 54.7959404
},
"Images": [
"https://upload.wikimedia.org/wikipedia/commons/thumb/8/8c/Flensborg_Fjord_ved_bockholmwik.jpg/400px-Flensborg_Fjord_ved_bockholmwik.jpg"
]
}
]
}
Image tag will always expect path for that image
<img src="./images/name.jpg" />
or
<img src="http:/wwww.sitename.com/images/name.jpg" />
what does you Image contain image path or image byte?
if it contain image byte then it has to be rendered separately by creating an intermediate page
Change the inner loop to:
foreach (var image in item.Images) //without the `#`
{
<img src="#image" /> //with " and />
}
This should work if the specified file exists. (if it doesn't work, show the full error + html :-)
Devbridge Autocomplete works with "lookup" but when I switch to serviceUrl it doesn't show the results. There are no errors and the json validates.
HTML:
<input type="text" name="currency" class="biginput" id="autocomplete" autocomplete="off">
JS:
$('#autocomplete').autocomplete({
//lookup: currencies,
serviceUrl: "http://localhost/agfg1Member/handlers/ACKeyword.ashx",
onSelect: function (suggestion) {
var thehtml = '<strong>Currency Name:</strong> ' + suggestion.value + ' <br> <strong>Symbol:</strong> ' + suggestion.data;
$('#outputcontent').html(thehtml);
},
dataType: 'jsonp',
minChars: 2 });
Example of json from c# ashx handler
({"suggestions":[{"value":"Tuggerah","data":{"category":"Suburb","id":"3371","parentCat":"3"}},{"value":"Tuggeranong","data":{"category":"Suburb","id":"3372","parentCat":"80"}},{"value":"Tugun","data":{"category":"Suburb","id":"3373","parentCat":"33"}}]})
The brackets make it jsonp. This is JSONLINT validated without the brackets:
{
"suggestions": [
{
"value": "Tuggerah",
"data": {
"category": "Suburb",
"id": "3371",
"parentCat": "3"
}
},
{
"value": "Tuggeranong",
"data": {
"category": "Suburb",
"id": "3372",
"parentCat": "80"
}
},
{
"value": "Tugun",
"data": {
"category": "Suburb",
"id": "3373",
"parentCat": "33"
}
}
]}
And the ashx file outputs context.Response.ContentType = "application/json";
I tried adding "jsonp: 'cb'" to the source code, still nothing.
Uses jquery.1.9.1
Also, when stepping through the javascript, the var response remains undefined. I don't know what this means, but it doesn't sound good, hey?
How can I iterate over the images in JSON of following format? Length of images collection can be arbitrary. Can I manipulate it to make it a list, or what options do I have to parse this?
images: {
0: {
filename: "image1.jpg"
},
1: {
filename: "image2.jpg"
},
2: {
filename: "image3.jpg"
},
}
One possible solution would be to create a dynamic representation of your json:
dynamic jsonData = JsonConvert.DeserializeObject(#"{
images: {
0: {
filename: ""image1.jpg""
},
1: {
filename: ""image2.jpg""
},
2: {
filename: ""image3.jpg""
}
}
}");
foreach(var item in jsonData["images"])
{
//Do something
}
If you have a read of this SO question, you'll notice that JSON.NET is a recommended library to use for situations like this.
You could try using the DataContractJsonSerializer to create objects from JSON input, but when I tried it just now, I couldn't get it to work with a collection of items in the JSON string.
You can do this with vanilla javascript like this:
for (objectName in data["images"]) {
html += data["images"][objectName]["filename"] + "<br />"
}
Full HTML file example below
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="result"></div>
<script type="text/javascript">
var data = {
"images": {
"0": {
"filename": "image1.jpg"
},
"1": {
"filename": "image2.jpg"
},
"2": {
"filename": "image3.jpg"
}
}};
var html = '';
for (objectName in data["images"]) {
html += data["images"][objectName]["filename"] + "<br />"
}
document.getElementById("result").innerHTML = html;
</script>
</body>
</html>
I ended up figuring it out - although may not be best practice it worked in this case
var imageHoldingList = new List<VehicleImagesModel>();
var connectionResponse = JsonConvert.DeserializeObject<dynamic>(results);
var jImage = connectionResponse["response"]["vehicles"]["images"].Children();
foreach (var image in jImage)
{
var h = new VehicleImagesModel
{
Filename = image.First.filename.ToString(),
Caption = image.First.caption.ToString()
};
imageHoldingList.Add(h);
}
I am trying to get jStree (jQuery tree control) working in my ASP.NET (C#) page. I'm using a WCF service to return a test string of JSON.
Opening the WCF service URL in the browser works fine - If I go to the URL (http://localhost/website/GetTree) I get the JSON (looks just like opening XML in browser, with syntax highlighting and collapsible tab thingys)
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">{"attr": { "id": 2, "rel": "default" }, "data": "A node", "children": [ { "data": "Child 1", "attr": { "id": 43, "rel": "document" } }, {"data": "Child 2", "attr": { "id": 25, "rel": "document"} } ] }</string>
jstree itself works fine - if I put the same JSON in "manually" in my document.ready like so:
"json_data": {
"data":
[{
"attr": { "id": 2, "rel": "default" },
"data": "A node",
"children":
[{
"data": "Child 1", "attr": { "id": 43, "rel": "document" }
},{
"data": "Child 2", "attr": { "id": 25, "rel": "document"}
}]},{
"attr": { "id": "li.node.id", "rel": "document" },
"data": {
"title": "Long format demo",
"attr": { "href": "#" }
}}]},
I get the tree appearing with those nodes in it.
But, combining the two:
"json_data": {
"ajax": {
"url": "GetTree",
"data": function (n) {
return {
};
}
}
},
...fails. The jstree shows up as just the word "loading..." and an animated loading gif. And it does hit a breakpoint inside the WCF service method (just like browsing to it does).
A: An idea where I've gone wrong?
B: An idea how I find out what's wrong? jstree documentation was no help, and I can't see any error messages.
Thanks.
Update: solved
Thanks to Mikael Eliasson for pointing out that my service must be returning XML and not JSON.
WCF service code-behind:
// this responseformat bit below fixed it
[WebGet(UriTemplate = "GetTesto", ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
public Testo GetTesto()
{
return new Testo();
}
Might be a stupid question but you have enabled the json_data plugin, right? As akonsu said inspecting the response in a tool like Firebug.
It seems to me that you WCF service is not returning JSON but rather a XML response. I think that is your problem. The best thing is probably to change the service to return JSON. If you can't do that you could add the success function and transform the string to JSON with the function $.parseJSON()
I hope that helps. But again you really should start using Firebug or something similar because there are lot of times when you need to inspect the response or debug javascript.