Using JSON.NET to return ActionResult
I found a similar stackoverflow question:
Json.Net And ActionResult
The answer there suggested using
return Content( converted, "application/json" );
That seems to work on my very simple page.
Json.Net And ActionResult
You should just be able to do this in your action method:
return Content( res.ToString(), "application/json" );
MVC 4 return JSON as ActionResult
Your problem is within the usings as the UmbracoApiController
most likely inherits from ApiController (from System.Web.Http)
not Controller (from System.Web.Mvc)
and thus they have different dependencies. To fix your problem first remove the
using System.Web.Mvc;
and put the
using System.Web.Http;
as for the return in this case that would be IHttpActionResult
so you would have something as follows:
using MailChimp;
using MailChimp.Helper;
using Opten.Polyglott.Web.Models;
using Opten.Umbraco.Common.Extensions;
using System.Configuration;
using System.Web.Http;
using Umbraco.Core.Logging;
using Umbraco.Web.WebApi;
namespace Opten.Polyglott.Web.Controllers
{
public class NewsletterApiController : UmbracoApiController
{
public IHttpActionResult Subscribe(Newsletter newsletter)
{
bool isSuccessful = false;
if (ModelState.IsValid)
{
isSuccessful = SubscribeEmail(newsletter.Email);
}
return Json(new { isSuccess = isSuccessful });
}
}
}
Let me know if that works for you.
ASP.NET Core return JSON with status code
The most basic version responding with a JsonResult
is:
// GET: api/authors
[HttpGet]
public JsonResult Get()
{
return Json(_authorRepository.List());
}
However, this isn't going to help with your issue because you can't explicitly deal with your own response code.
The way to get control over the status results, is you need to return a
ActionResult
which is where you can then take advantage of theStatusCodeResult
type.
for example:
// GET: api/authors/search?namelike=foo
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
var result = _authorRepository.GetByNameSubstring(namelike);
if (!result.Any())
{
return NotFound(namelike);
}
return Ok(result);
}
Note both of these above examples came from a great guide available from Microsoft Documentation: Formatting Response Data
Extra Stuff
The issue I come across quite often is that I wanted more granular control over my WebAPI rather than just go with the defaults configuration from the "New Project" template in VS.
Let's make sure you have some of the basics down...
Step 1: Configure your Service
In order to get your ASP.NET Core WebAPI to respond with a JSON Serialized Object along full control of the status code, you should start off by making sure that you have included the AddMvc()
service in your ConfigureServices
method usually found in Startup.cs
.
It's important to note that
AddMvc()
will automatically include the Input/Output Formatter for JSON along with responding to other request types.
If your project requires full control and you want to strictly define your services, such as how your WebAPI will behave to various request types including application/json
and not respond to other request types (such as a standard browser request), you can define it manually with the following code:
public void ConfigureServices(IServiceCollection services)
{
// Build a customized MVC implementation, without using the default AddMvc(), instead use AddMvcCore().
// https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc/MvcServiceCollectionExtensions.cs
services
.AddMvcCore(options =>
{
options.RequireHttpsPermanent = true; // does not affect api requests
options.RespectBrowserAcceptHeader = true; // false by default
//options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
//remove these two below, but added so you know where to place them...
options.OutputFormatters.Add(new YourCustomOutputFormatter());
options.InputFormatters.Add(new YourCustomInputFormatter());
})
//.AddApiExplorer()
//.AddAuthorization()
.AddFormatterMappings()
//.AddCacheTagHelper()
//.AddDataAnnotations()
//.AddCors()
.AddJsonFormatters(); // JSON, or you can build your own custom one (above)
}
You will notice that I have also included a way for you to add your own custom Input/Output formatters, in the event you may want to respond to another serialization format (protobuf, thrift, etc).
The chunk of code above is mostly a duplicate of the AddMvc()
method. However, we are implementing each "default" service on our own by defining each and every service instead of going with the pre-shipped one with the template. I have added the repository link in the code block, or you can check out AddMvc()
from the GitHub repository..
Note that there are some guides that will try to solve this by "undoing" the defaults, rather than just not implementing it in the first place... If you factor in that we're now working with Open Source, this is redundant work, bad code and frankly an old habit that will disappear soon.
Step 2: Create a Controller
I'm going to show you a really straight-forward one just to get your question sorted.
public class FooController
{
[HttpPost]
public async Task<IActionResult> Create([FromBody] Object item)
{
if (item == null) return BadRequest();
var newItem = new Object(); // create the object to return
if (newItem != null) return Ok(newItem);
else return NotFound();
}
}
Step 3: Check your Content-Type
and Accept
You need to make sure that your Content-Type
and Accept
headers in your request are set properly. In your case (JSON), you will want to set it up to be application/json
.
If you want your WebAPI to respond as JSON as default, regardless of what the request header is specifying you can do that in a couple ways.
Way 1
As shown in the article I recommended earlier (Formatting Response Data) you could force a particular format at the Controller/Action level. I personally don't like this approach... but here it is for completeness:
Forcing a Particular Format If you would like to restrict the response formats for a specific action you can, you can apply the
[Produces] filter. The [Produces] filter specifies the response
formats for a specific action (or controller). Like most Filters, this
can be applied at the action, controller, or global scope.[Produces("application/json")]
public class AuthorsController
The
[Produces]
filter will force all actions within the
AuthorsController
to return JSON-formatted responses, even if other
formatters were configured for the application and the client provided
anAccept
header requesting a different, available format.
Way 2
My preferred method is for the WebAPI to respond to all requests with the format requested. However, in the event that it doesn't accept the requested format, then fall-back to a default (ie. JSON)
First, you'll need to register that in your options (we need to rework the default behavior, as noted earlier)
options.RespectBrowserAcceptHeader = true; // false by default
Finally, by simply re-ordering the list of the formatters that were defined in the services builder, the web host will default to the formatter you position at the top of the list (ie position 0).
More information can be found in this .NET Web Development and Tools Blog entry
.Net Core Get json result from another controller action and convert the json string into c# object
Create a common service to reuse the logic:
public class MyAccountService{
private AppDbContext _context;
public MyAccountService(AppDbContext context){
this._context = context;
}
public int GetTotal(int AccountId){
Account account=this._context.Accounts.FirstOrDefault(s=>s.Id=AccountId);
return account.Sum(s=>s.Amount);
}
}
register it as a scoped service.
services.AddDbContext<AppDbContext>(options =>options.UseSqlServer(Configuration.GetConnectionString("AppDbContext")))
services.AddScoped<MyAccountService>();
And inject this service in your controllers as you need:
public class A1Controler :{
private AccountService _accountService
public A1Controller(MyAccountService accountService){
this._accountService=accountService;
}
[HttpPost]
public ActionResult GetTotal(int AccountId)
{
var theTotal=this._accountService.GetTotal(AccountId);
return Json(theTotal);
}
}
If you have another A2Controller
, simply do the same injection.
Related Topics
Reading Excel Files as a Server Process
Create a Coroutine to Fade Out Different Types of Object
How Much Faster Is C++ Than C#
Checking If an Object Is Null in C#
Generate a Self-Signed Certificate on the Fly
Difference Between Char.Isdigit() and Char.Isnumber() in C#
Mvcbuildviews Not Working Correctly
How to Replace Part of String by Position
How to Programmatically Change Active Directory Password
Can a Class Library Have an App.Config File
How to Best Implement Equals for Custom Types
Characters in String Changed After Downloading HTML from the Internet
Iequalitycomparer<T> That Uses Referenceequals
How to Show the Sum of in a Datagridview Column
Put Wpf Control into a Windows Forms Form
Implementing Audit Log/Change History with MVC & Entity Framework