Returning Json from an MVC controller that extends Apicontroller - asp.net-mvc

I'm trying to return a Json string from an MVC controller in a WebAPI application, but am unable to use return Json(... because the class being used extends ApiController and not Controller (I believe).
Is there an alternative method to do what I'm trying to do (e.g. return a different type)? Or a workaround?
This is my controller code:
public class SocialController : ApiController
{
public ActionResult Get(SocialRequest request) // or JsonResult?
{
JavaScriptSerializer js = new JavaScriptSerializer();
string jsontest = js.Serialize(request); // just serializing back and forth for testing
return Json(jsontest, JsonRequestBehavior.AllowGet);
}
}
The error I'm receiving is "System.Web.Helpers.Json is a type but is used like a variable."
I've found the following related SO question but it hasn't solved it for me, if anyone can elaborate I'd really appreciate it (and dish out the rep points):
Why Json() Function is unknown

In Asp.net Web Api you don't have ActionResults anymore. You simply return the object you need. The framework converts the object to the proper response (json, xml or other types)
[HttpGet]
public IEnumerable<string> GetUsers(SocialRequest request)
{
return _applicationsService.GetUserss(request);
}

Related

Implementing data interface in ASP.NET MVC Controller and returning JSON

I would like to have my Controller implement my data interface that returns custom objects. All the objects are serializable and decorated by JSON attributes. So I would like to have my controller method simply be that:
public class MyController : Controller, IMyInterface
{
public Foo[] GetFoosByName(string name)
{
return new Foo[]{new Foo(name), new Foo(name)}
}
}
If I do it I get simply "Foo[]" response. What I'd like to get is JSON-serialized Foo objects.
I can easily achieve this by changing my response to be JsonResult:
public JsonResult GetFoosByName(string name)
{
return Json(new Foo[]{new Foo(name), new Foo(name)});
}
But then I won't be able to implement IMyInterface in the way that is easily maintainable.
Any ideas on how I can automatically get the behavior as I was returning JsonResult, but still keeping original return types?
Generally I would recommend against such a pattern. An MVC Controller should ideally be kind of a top-most layer, and I think it should not implement interfaces. You should implement such interfaces in a service layer, below the MVC Controllers.
However, if you still want to do it so, you can use explicit implementation like this.
public class MyController : Controller, IMyInterface
{
public JsonResult GetFoosByName(string name)
{
return Json(((IMyInterface)this).GetFoosByName(name));
}
Foo[] IMyInterface.GetFoosByName(string name)
{
return new[] { new Foo(name) };
}
}

Is it possible to select an Action with AttributeRouting in .NET MVC based on the Media Type of the Accept header?

I want to select an Action of my Controller based on the Media Type requested in the Accept header.
For example, I have a resource called a subject. Its assigned route is:
GET /subjects/{subjectId:int}
Normally, the browser is requesting text/html, which is fine. The default Media Formatter handles this great.
Now, I have custom logic I want to perform when this same route is accessed with an accept header specifying application/pdf as the accepted Media Type.
I could create a custom Media Formatter, but, to my understanding, this would mean that any route that is requested with the Accept header set to application/pdf would also run through this Media Formatter. This is unacceptable.
In Java, there is an annotation called #Produces:
The #Produces annotation is used to specify the MIME media types or
representations a resource can produce and send back to the client. If
#Produces is applied at the class level, all the methods in a resource
can produce the specified MIME types by default. If applied at the
method level, the annotation overrides any #Produces annotations
applied at the class level.
This would allow me to do the following:
namespace MyNamespace
{
[RoutePrefix("subjects")]
public class SubjectsController : Controller
{
[Route("{subjectId:int}")]
[HttpGet]
public ActionResult GetSubject(int subjectId)
{
}
[Route("{subjectId:int}")]
[HttpGet]
[Produces("application/pdf")]
public ActionResult GetSubjectAsPdf(int subjectId)
{
//Run my custom logic here to generate a PDF.
}
}
}
There is no Produces Attribute in .NET that I can find, of course, so this doesn't work. I haven't been able to find a similar attribute, either.
I could of course manually check the header within the body of the action, and redirect it to another action, but that seems hackish at best.
Is there a mechanism in .NET 4.5 that I may use to pull this off that I'm overlooking or missing?
(I'm using MVC 5.2.2 from NuGet repository)
After searching around the Internet for awhile, I came up with the idea that this would be best accomplished by creating an ActionMethodSelectorAttribute.
The following is a very naive, first-pass implementation of a ProducesAttribute that I wrote with the eventual intent of mimicking Java's Produces annotation:
namespace YourNamespace
{
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Mime;
using System.Web.Mvc;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class ProducesAttribute : ActionMethodSelectorAttribute
{
private readonly ISet<ContentType> acceptableMimeTypes;
public ProducesAttribute(params string[] acceptableMimeTypes)
{
this.acceptableMimeTypes = new HashSet<ContentType>();
foreach (string acceptableMimeType in acceptableMimeTypes)
this.acceptableMimeTypes.Add(new ContentType(acceptableMimeType));
}
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
{
string acceptHeader = controllerContext.RequestContext.HttpContext.Request.Headers[HttpRequestHeader.Accept.ToString()];
string[] headerMimeTypes = acceptHeader.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries);
foreach (var headerMimeType in headerMimeTypes)
{
if (this.acceptableMimeTypes.Contains(new ContentType(headerMimeType)))
return true;
}
return false;
}
}
}
It is meant to be used with Attribute Routing, and can be applied as follows:
public sealed class MyController : Controller
{
[Route("subjects/{subjectId:int}")] //My route
[Produces("application/pdf")]
public ActionResult GetSubjectAsPdf(int subjectId)
{
//Here you would return the PDF representation.
}
[Route("subjects/{subjectId:int}")]
public ActionResult GetSubject(int subjectId)
{
//Would handle all other routes.
}
}

How can I get the raw JSON dictionary from ASP.NET MVC Web API post?

With a ApiController subclass, it has the ability in Post method to bind it to an existing model object such as
public class RegisterController : ApiController
{
public void Post(Product product)
but if the incoming JSON data contains data that I'll use to create multiple model objects, how can I get to the data directly?
public void Post(dynamic value)
returns value as null. Is there an easy shorthand way of getting to it like request.POST['name'] or something?
Let's say the data looks like
{
'productID':1,
'productName':'hello',
'manufacturerID':1,
'manufacturerName':'world'
}
One option may be using one of the ReadAsAsync* methods in HttpContent instance off of the Request object
public void Post() {
var result = this.Request.Content.ReadAsAsync<string>().Result;
}
I don't know what format you're sending your data in, but you can retrieve it this way.
You could try this too for multiple objects...
public void Post(IEnumberable<Product> products) {
}

Accessing resources via Uri in Asp.net mvc

I am working on an ASP.NET MVC web application in which I have an object with a Uri property. The Uri contains a restful link to a resource in the following form:
/Repository/Dataset/5
The Dataset action of the Repository controller returns the contents of dataset 5 as Json.
How do I call this method from the Uri and interpret the response as Json from within the object?
Many thanks.
In server side action return JsonResult.
public ActionResult Dataset(int id)
{
// reository code
return Json(model);
}
client side call $.getJSON.
My opinion is that you should not call your controller from anywhere in code.In ASP.NET MVC Controller is there to accept request, take data and choose proper view to be returned back.
Maybe you should add method on repository that is returning already JSONized data, or introduce "Middle man" that can serialize data returned from repository so controller can call middle man to do the job. Then repository (or "Middle man") can be called from anywhere in code.
e.g.(used Json.NET for json serialization):
public class MiddleMan
{
IRepository repository
public MiddleMan(IRepository repository)
{
this.repository = repository;
}
public string GetJsonObjects(int id)
{
return JsonConvert.SerializeObject(repository.GetObject(id));
}
}
then controller (or anywhere in the code) can call this middle class:
public string Dataset(int id)
{
return new MiddleMan(repository).GetJsonObjects(id);
}
For the time being I'm going to implement a uri extension method something along these lines, creating a WebRequest object for the Uri.
public static string GetContent(this Uri uri)
{
var myRequest = (HttpWebRequest) WebRequest.Create(uri);
myRequest.Method = "GET";
WebResponse myResponse = myRequest.GetResponse();
var sr = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8);
string result = sr.ReadToEnd();
sr.Close();
myResponse.Close();
return result;
}

Binding application/json to POCO object in asp.net mvc, Serialization exception

I'm passing json back up from my view to my controller actions to perform operations. To convert the json being sent in, to a POCO I'm using this Action Filter:
public class ObjectFilter : ActionFilterAttribute {
public Type RootType { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext) {
IList<ErrorInfo> errors = new List<ErrorInfo>();
try {
object o = new DataContractJsonSerializer(RootType).ReadObject(filterContext.HttpContext.Request.InputStream);
filterContext.ActionParameters["postdata"] = o;
}
catch (SerializationException ex) {
errors.Add(new ErrorInfo(null, ex.Message));
}
finally {
filterContext.ActionParameters["errors"] = errors.AsEnumerable();
}
}
It's using the DataContractJsonSerializer to map the JSON, over to my object. My Action is then decorated like so:
[ObjectFilter(RootType = typeof(MyObject))]
public JsonResult updateproduct(MyObject postdata, IEnumerable<ErrorInfo> errors) {
// check if errors has any in the collection!
}
So to surmise, what is going on here, if there is a problem serializing the JSON to the type of object (if a string cannot be parsed as a decimal type or similar for eg), it adds the error to a collection and then passes that error up to the view. It can then check if this collection has an errors and report back to the client.
The issue is that I cannot seem to find out which field has caused the problem. Ideally I'd like to pass back to the view and say "THIS FIELD" had a problem. The SerializationException class does not seem to offer this sort of flexibility.
How would the collective SO hivemind consider tackling this problem?
I would just do an ajax form post. It's much easier.
http://plugins.jquery.com/project/form
http://malsup.com/jquery/form/
How about this: Json.Net
It reads a JSON string and then Deserialises it to the given POCO object.
string jsonResult = GetJsonStringFromSomeService();
MyPocoObject myobject = JsonConvert.DeserializeObject<MyPocoObject>(jsonResult);
Console.Write("Damn that is easy");
But for the determing where errors occur, I am not too sure.

Resources