Get JSON data out of Umbraco - c#

I am a frontend developer so forgive my lack of ability to explain my issue.
I am trying to create some pages in an Umbraco project that display data using Vue.js. For this, I am trying to set up a custom API controller that will return the data I want, when called.
A simple example would be that I want to return all blog articles. Below is the code I have currently got:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Web;
using System.Web.Http;
using Umbraco.Web.WebApi;
using Umbraco.Web.PublishedContentModels;
using Newtonsoft.Json;
namespace Controllers.WebAPI.Qwerty
{
[Route("api/[controller]")]
public class PostsApiController : UmbracoApiController
{
[HttpGet]
public string Test()
{
return "qwerty";
}
}
}
I've read numerous articles and just can't seem to grasp what I need to do to query Umbraco for the data I want back?
I've tried adding
var content = Umbraco.TypedContent(1122);
And then returning that but I get errors stating:
(local variable) Umbraco.Core.Models.IPublishedContent content
Cannot implicitly convert type 'Umbraco.Core.Models.IPublishedContent' to 'string'
I have then tried serialising the var content but I get stuck with:
Self referencing loop detected for property 'FooterCtalink' with type
'Umbraco.Web.PublishedContentModels.Blog'. Path
'ContentSet[0].FeaturedProducts[0].Features[0].ContentSet[0]'.
Any help would be fantastic!
EDIT:
I have no edited the controller to be like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Web;
using Umbraco.Web.WebApi;
using Umbraco.Web.PublishedContentModels;
using Newtonsoft.Json;
using System.Web.Mvc;
using DTOs.PostDTO;
namespace Controllers.WebAPI.Qwerty
{
[Route("api/[controller]")]
public class PostsApiController : UmbracoApiController
{
[HttpGet]
public PostDTO Test()
{
// 1. Get content from umbraco
var content = Umbraco.TypedContent(1122);
// 2. Create instance of your own DTO
var myDTO = new PostDTO();
// 3. Pupulate your DTO
myDTO.Url = content.Url;
// 4. return it
return myDTO;
}
}
}
And created a DTO like so:
namespace DTOs.PostDTO
{
public class PostDTO
{
public string Url { get; set; }
}
}
However, when console logging my data after the ajax request, I only only getting 1122.

The issue is that you can't return a .NET Object in JSON that has the circular dependency.
To solve your problem, you can simply follow the below steps:
Create your own DTO & add required properties in that.
Fetch content from Umbraco API in C# & populate your custom DTO object.
Return that DTO from JsonResult.
Your code will look like below:
[Route("api/[controller]")]
public class PostsApiController : UmbracoApiController
{
[HttpGet]
public MyDTO Test()
{
// 1. Get content from umbraco
var content = Umbraco.TypedContent(1122);
// 2. Create instance of your own DTO
var myDTO = new MyDTO();
// 3. Pupulate your DTO
myDTO.SomeProperty = content.SomeProperty;
// 4. return it
return myDTO;
}
}

You are on the right track.
I think you need to return ActionResult instead of string.
Something like:
[HttpGet]
public ActionResult Test()
{
var content = Umbraco.TypedContent(1122);
return new JsonResult(content);
}
This should return the umbraco object as Json.

Related

REST Server connection reset on Routing path

Question is: Did I define the client resource call correctly, or is there something wrong in the server code?
I have a REST API server I am coding in C# / Visual Studio 2019 using the Web API template. I have 2 paths at the moment - a POST and a GET.
POST: /api/account
GET: /api/account/{accountid:long}
POST works great using SoapUI as a test client, but GET gives me a connection reset (message is "Error getting response; java.net.SocketException: Connection reset").
I hope I defined the resource correctly:
Here's my Controller code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Newtonsoft.Json.Linq;
using Coda.Core;
using CodaRESTServer.Models;
using System.IO;
using System.Diagnostics;
namespace MyRESTServer.Controllers
{
[RoutePrefix("api/account")]
public class AccountController : ApiController
{
[HttpGet]
[Route("{accountid:long}")]
// GET api/<controller>/5
public JObject Get(long accountid)
{
var x = new JObject();
x["worked"] = "true";
return (x);
}
[HttpPost]
[Route("")]
// POST api/account
public JObject Post()
{
var x = new JObject();
x["worked"] = "true";
return (x);
}
}
}
I specified it wrong in SoapUI. It needs to be:
/api/account/{accountid}
And then I can click on the Parameters field and enter the value.

How to return a JSON from WebAPI using http request?

I'm trying to implement a new web API. This API returns a JSON from HTTP-request.
So far I wrote very basic code, but the strange thing is that I get an error using XML template - and I have no idea what to do:
This is the call: http://localhost:55643/api/ShipmentsStatus/getShipmentsStatusJSON
The code is here:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace RunCom.WebAPI.Controllers
{
[Route("api/[controller]")]
public class ShipmentsStatusController : ApiController
{
// /api/ShipmentsStatus/getShipmentsStatusJSON
public ShipmentsStatusController()
{
int i = 0;
}
[HttpGet]
[Route("getShipmentsStatusJSON")]
public IEnumerable<String> Get()
{
test check = new test("1");
yield return JsonConvert.SerializeObject(check);
}
}
internal class test
{
string key;
public test(string k)
{
key = k;
}
}
}
The error I got is here:
<Error>
<Message>No HTTP resource was found that matches the request URI
'http://localhost:55643/api/ShipmentsStatus/getShipmentsJSON'.</Message>
<MessageDetail>No action was found on the controller 'ShipmentsStatus' that matches the request.</MessageDetail>
</Error>
What is wrong with my code?
Try to fix the route
[Route("~/api/ShipmentsStatus/GetShipmentsStatusJSON")]
public IEnumerable<string> Get()
{
return new List<string> {"1","2","3"};
}
You should use http://localhost:55643/api/ShipmentsStatus/getShipmentsStatusJSON or change [Route("getShipmentsStatusJSON")] to the appropriate API method name

How can I connect to a broker using MQTT in MVC framework?

I'm trying to set up an MQTT connection to a test broker: "test.mosquitto.org" in C# using MVC(this one is just for practise). Eventually I want to make a web application that collects and shows data from databases on different locations. There seem to be no tutorials for MVC framework so I'm following this example: https://gist.github.com/cwschroeder/7b5117dca561c01def041e7d4c6d2771.
The hard part for me is converting that example to MVC framework(with the controllers, models, etc.)
So I have a few questions about this:
Is there a better/easier option for this than MVC?
What framework is used in the sample?
What would be my first steps to set up a connecting to a broker in MVC?(also wondering if it would be possible to see an example in code)
I already added some properties and a start + installed the M2mqtt library.
No idea where to go from here. I wish I could just copy paste the sample but that is obviously not possible with MVC.
MqttClientController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using uPLibrary.Networking.M2Mqtt.Session;
using MvcTestMqtt.Models;
namespace MvcTestMqtt.Controllers
{
public class MqttClientController : Controller
{
// GET: MqttClient
public ActionResult Index()
{
return View();
}
public ActionResult ConnectClient()
{
var mqtt = new MqttModel();
new MqttClient(mqtt.BrokerAddress);
new MqttClient(mqtt.clientID);
return View();
}
}
}
MqttModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using MvcTestMqtt.Controllers;
namespace MvcTestMqtt.Models
{
public class MqttModel
{
MqttClient client { get; set; }
public string clientID { get; set; }
public string BrokerAddress = "test.mosquitto.org";
}
}

WebAPI POST [FromBody] Not Binding and Not Throwing Up Error

I'm trying to understand why my JSON Object when casted to an specficied object is giving me NULL when one of the attributes sent im my json, which is a number, is larger than Int32. My whole object is not binding and not not throwing up any error, just becoming null.
Now my situation. I started a new project just to understand it, and I all the question over here I could found.
I do have this model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace TestJson.Models
{
public class Credential
{
public int IdSource { get; set; }
public DateTime TransactionDate { get; set; }
}
}
I have this Controller:
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using TestJson.Models;
namespace TestJson.Controllers
{
[RoutePrefix("PreAuth")]
public class PreAuthController : ApiController
{
[HttpPost]
[ActionName("PostObject")]
public async Task<IHttpActionResult> PostObject([FromBody]Credential input)
{
return await Task.FromResult(Ok(input));
}
[HttpPost]
[ActionName("PostJObject")]
public async Task<IHttpActionResult> PostJObject([FromBody]JObject input)
{
Credential Credential = input.ToObject<Credential>();
return await Task.FromResult(Ok(Credential));
}
}
}
And I have this JSON object:
{
"IdSource": 11111111111111,
"TransactionDate": "2017-11-24T11:59:01.7567643-02:00"
}
So, when I calling api/PreAuth/PostObject within the above JSON, I just get null as parameter casted to my object.
But if I call the same JSON /api/PreAuth/PostJObject, I can receive the given error below:
{
"Message": "An error has occurred.",
"ExceptionMessage": "Value was either too large or too small for an Int32.",
"ExceptionType": "System.OverflowException",
"StackTrace": " em System.Convert.ToInt32(Int64 value)..."
}
So, If I change my JSON object modifying my IdSource attribute to a shorter number, both of my methods works fine because it can fit to int limits.
My point is; Why when I call the method PostObject expecting a specified object in parameter and it couldn't cast my JSON into it properly it is giving me null and not filling my others properties?
The best scenario would be at least see some error, but I just get nothing at all. All my object is swallowed and it becomes like an stealth error and the caller don't know exactly which attribute he is giving wrong.
How can I workaround this using object as parameter instead JObject?
You should configure your JsonFormatter on your HttpConfiguration (application Startup).
An example:
protected virtual void ConfigureFormatter(HttpConfiguration config)
{
JsonConvert.DefaultSettings = () =>
{
JsonSerializerSettings result = new JsonSerializerSettings();
//Include the type name to be able to deserialize into the derived instead of the base type.
result.TypeNameHandling = TypeNameHandling.Auto;
//Do not include null properties in serialized JSON.
result.NullValueHandling = NullValueHandling.Ignore;
return result;
};
JsonMediaTypeFormatter jsonFormatter = config.Formatters.JsonFormatter;
jsonFormatter.SerializerSettings = JsonConvert.DefaultSettings();
config.Formatters.Clear();
config.Formatters.Add(jsonFormatter);
config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));
}
EDIT
The previous answer works for extended objects (I thought your were having null values on that).
You can however add a custom filter for filtering valid models like explained here:
Capture exception during request deserialization in WebAPI C#

ASP.NET Syntax and conventions

I am reading Designing Evolvable Web APIs with ASP.NET. In one of the exercises, the book has me edit a Controller using Visual Studio. This is being done in ASP.NET using C#. The template I used was the standard ASP.NET web application API.
I have edited the controller to the way the book shows (although it does not seem to give very specific directions). Here is what my controller looks like.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OAuth;
using WebApplication4.Models;
using WebApplication4.Providers;
using WebApplication4.Results;
namespace WebApplication4.Controllers
{
public class GreetingController : ApiController
{
public string GetGreeting() {
return "Hello World!";
}
}
public static List<Greeting> _greetings = new List<Greeting>();
public HttpResponseMessage PostGreeting(Greeting greeting)
{
_greetings.Add(greeting);
var greetingLocation = new Uri(this.Request.RequestUri, "greeting/" + greeting.Name);
var response = this.Request.CreateResponse(HttpStatusCodeResult.Created);
response.Headers.Location = greetingLocation;
return response;
}
}
I get errors on:
_greetings: A namespace cannot directly contain members such as fields or methods
PostGreeting: A namespace cannot directly contain members such as fields or methods,
_greetings : does not exist in the current context
Request : <invalid-global-code> does not contain a definition for 'request',
Created: HttpStatusCodeREsult does not contain a definition for 'Created'
As the error is trying to tell you, your fields and methods must be inside the class.
Check your braces.
Your _greetings field needs to be part of the class, as well as the PostGreeting method, it seems you just closed "}" of the class a bit early.
MOve the "}" before the _greetings field to the end of the file, like:
namespace WebApplication4.Controllers
{
public class GreetingController : ApiController
{
public string GetGreeting() {
return "Hello World!";
}
public static List<Greeting> _greetings = new List<Greeting>();
public HttpResponseMessage PostGreeting(Greeting greeting)
{
_greetings.Add(greeting);
var greetingLocation = new Uri(this.Request.RequestUri, "greeting/" + greeting.Name);
var response = this.Request.CreateResponse(HttpStatusCodeResult.Created);
response.Headers.Location = greetingLocation;
return response;
}
}
}

Categories

Resources