1

I need to send/receive data to/from C# API without using a model.

I've for testing purposes, the below JS:

fetch('/login', {
     method: 'post',
     body: JSON.stringify({
         email: 'hasan@gmail.com', //document.getElementById('email').value
         pswd: '1234' //document.getElementById('answer').value
     })
})
.then(function(response) {
  return response.text();
  // return response.json();
}).then(function(text) { 
  // console.log(text); 
});

where I need to send the username and password, and need the server to send back some confirmations.

The Controller used in C# is:

[Route("/login")]
public class FetchController
{
    [HttpPost]
    public async Task Post(String loginParam)
    {
         if (loginParam != null)
           {
            Console.WriteLine("Login Data Recieved");
           }
           else
           {
           Console.WriteLine("Login Data is NULL");
          }
        Console.WriteLine(loginParam);
        var response = _httpContextAccessor.HttpContext.Response;
        response.Headers.Add("Content-Type", "text/event-stream");
        response.StatusCode = 200;
            await response
                .WriteAsync($"user logged in at {DateTime.Now}\r\r");   
            response.Body.Flush();
    }
}

Here I keep getting the Login data is NULL, I know this is as I did not bind the login data to Model class, so how can I make the above working WITHOUT using MODEL binding

Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203
  • You not sending any data with a name `model`. You sending values for `email` and `pswd` so you need parameters to match that –  Oct 30 '16 at 08:17
  • @StephenMuecke I'm sending JSON, so I need to read JSON or something that I can convert to JSON without defining any `Model` – Hasan A Yousef Oct 30 '16 at 08:26
  • Also don't write to response stream, you can just return a string or JSON or whatever you want from the method and it will be the correct way of doing – Sami Kuhmonen Oct 30 '16 at 08:27
  • Why do you not want to do this correctly using a model? But you can always just use `Post(string email, string pswd)` –  Oct 30 '16 at 08:30
  • You could manually retrieve the body from the request. Or you can use a dynamic object as action parameter instead of a string. Still I would just create a model. Why do you want to avoid creating a model? – ErazerBrecht Oct 30 '16 at 08:41
  • @StephenMuecke appreciate your interest to help, but the your proposal did not work. – Hasan A Yousef Oct 30 '16 at 08:42
  • @ErazerBrecht can you explain more pls, I did not get you. – Hasan A Yousef Oct 30 '16 at 08:42
  • @SamiKuhmonen I did no get your point, can you pls explain more. thanks – Hasan A Yousef Oct 30 '16 at 08:43
  • `$.post('@Url.Action("login")', { email: 'hasan@gmail.com', pswd: '1234' })` will work just fine. –  Oct 30 '16 at 08:45
  • Reading body manually http://stackoverflow.com/a/35590209/2961887 – ErazerBrecht Oct 30 '16 at 08:45
  • Using dynamic object http://stackoverflow.com/a/14073429/2961887 – ErazerBrecht Oct 30 '16 at 08:46
  • By dedault webApi will try to take that from Uri, as /login?loginParam="YOUR_JSON_HERE", Please have a look at my mvc sample, and in your case , mark the param with [FromBody] attribute – Ermir Beqiraj Oct 30 '16 at 09:27
  • You can use dictionary, take a look at http://stackoverflow.com/a/40029615/5426333 – adem caglin Oct 30 '16 at 10:43
  • @HasanAYousef: Please use [tag:asp.net-core-mvc`] tag in future, instead of [tag:asp.net-mvc]. Later one is for the legacy ASP.NET webstack – Tseng Oct 30 '16 at 14:03
  • @HasanAYousef Did you looked at the sample I provided ? It is under WebApi core, and Fetch api working correctly, sending data from index.html to FetchController and getting back the same data – Ermir Beqiraj Oct 30 '16 at 14:03
  • @E.B your example is working fine, but could not replicate it in mine yet, may I got tired, I'll check tomorrow and confirm you, thanks – Hasan A Yousef Oct 30 '16 at 14:15

2 Answers2

1

Note that you must match parameter name, and try to mark the param as [FromBody], since the webapi will try to read that as fromUrl.

Here is a working sample:

Javascript/JQuery

    function callFnc() {
        var loginParam = JSON.stringify({ email: 'hasan@gmail.com', pswd: '1234' });
        $.post("/Fetch/login", { loginParam : loginParam })
              .done(function (data) {
                  alert("Data Loaded: " + data);
              });
    }

C#

    [HttpPost]
    public ActionResult Login(string loginParam)
    {
        if (loginParam != null)
        {
            Console.WriteLine("Login Data Recieved");
        }
        else
        {
            Console.WriteLine("Login Data is NULL");
        }
        Console.WriteLine(loginParam);
        return new JsonResult() { Data = "Ok" };
    }

Here is the result:

enter image description here

ps: the sample is in mvc instead of webapi, however they are similar

Edit with Fetch

Note: Your problem in here is not in c#, it is all in fetch APi, if you can, get rid of it.

Here is an Example I made using Fetch,

Javascript

    function useFetch() {
        var loginParam = JSON.stringify({ email: 'hasan@gmail.com', pswd: '1234' });
        fetch('/Home/login', {
            method: 'post',
            headers: new Headers({
                'Content-Type': 'application/json'
            }),
            body: loginParam
        });
    }

C#

    [HttpPost]
    public JsonResult Login([FromBody]object loginParam)
    {
        if (loginParam != null)
        {
            Console.WriteLine("Login Data Recieved");
        }
        else
        {
            Console.WriteLine("Login Data is NULL");
        }
        Console.WriteLine(loginParam);
        return Json("OK");
    }

Result enter image description here

and Project

Ermir Beqiraj
  • 867
  • 11
  • 24
  • Still NULL, I changed the type from `(string loginParam)` to `(object loginParam)` so got `Data Recieved` but is printed as empty object `{}` but if I added the `([FromBody] object loginParam)` nothing got executed at all. Note: Could not use the `JsonResult()` as it is not availabe in .NET CORE – Hasan A Yousef Oct 30 '16 at 10:19
  • Are you sure you are trying the exact model that you have written in here ? – Ermir Beqiraj Oct 30 '16 at 11:14
  • @Hasan It Works in the same way, the return type doesn't matter, in case you need some complete sample, [here](https://www.dropbox.com/s/r6j0fpib1q4wczm/JQueryTestCore.zip?dl=0) is where you can get the whole project. – Ermir Beqiraj Oct 30 '16 at 11:15
  • @HasanAYousef Your problem is not in C#, it's at Fetch api, check my updated answer. Please let me know if it still doesn't work! – Ermir Beqiraj Oct 30 '16 at 12:14
  • Your project is working fine, but m app not, I even tried to change the `fetch` to normal `xmlHttp`, my project is here if you can have a look https://drive.google.com/open?id=0B2Zxj-0OeOEoNWFIcWwtLUctVWc – Hasan A Yousef Oct 30 '16 at 12:24
  • @HasanAYousef how do you call the action? – Ermir Beqiraj Oct 30 '16 at 13:44
  • @HasanAYousef [here](https://www.dropbox.com/s/xnop49aei52jv4c/Fetch%20WebApi%20Core.zip?dl=0) is the sample with webapi core and sample call that works just fine. Go to test page as http://localhost:20618/StaticFiles/Index.html – Ermir Beqiraj Oct 30 '16 at 13:47
  • your example is working fine, but could not replicate it in mine yet, may I got tired, I'll check tomorrow and confirm you, thanks – Hasan A Yousef Oct 30 '16 at 14:15
  • can you help in this: http://stackoverflow.com/questions/40612533/accessing-static-files-in-scd – Hasan A Yousef Nov 15 '16 at 15:40
0

Though I accepted E.B. answer, I just liked to re-write the full working code below, as it could be helpfull for some one in the future:

project.json:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
    "Microsoft.AspNetCore.Mvc": "1.0.1",
    "Microsoft.AspNetCore.StaticFiles": "1.0.0",
    "Microsoft.AspNetCore.Cors":"1.0.0"
  },
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.0.1"
        }
      },
      "imports": "dnxcore50"
    }
  }
}

Program.cs:

using System.IO;  // for Directory
using Microsoft.AspNetCore.Hosting;  // for WebHostBuilder()

namespace ApiCall
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }
}

Startup.cs:

using Microsoft.AspNetCore.Builder;   // for IApplicationBuilder and FileServerOptions
using Microsoft.AspNetCore.Hosting;  // for IHostingEnvironment
using Microsoft.Extensions.DependencyInjection;  // for IServiceCollection

namespace ApiCall
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors();  // to be accesssed from external sites, i.e. outside the server
            // Add framework services.
            services.AddMvc();   // to use Controllers
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
                app.UseFileServer();  // to be accessed from files in the server inside wwwroot folde
                app.UseCors(builder =>   // to be accesssed from external sites, i.e. outside the server
                        builder.AllowAnyOrigin()
                               .AllowAnyHeader()
                               .AllowAnyMethod()
                               .AllowCredentials()
                        );

            app.UseMvc();
        }
    }
}

Controllers / FetchController.cs:

using System;    // for Console.WriteLine
using Microsoft.AspNetCore.Mvc;  // for Controller, [Route], [HttpPost], [FromBody], JsonResult and Json 

namespace ApiCall.Controllers
{
    [Route("api/[controller]")]
    public class FetchController : Controller
    {
        // POST api/values
        [HttpPost]
        public JsonResult Post([FromBody]object loginParam)
        {
            Console.WriteLine(loginParam);
            return Json(loginParam);
        }

    }
}

wwwroot / index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <h2>
        Test page for using ajax call in webapi core.
    </h2>
    <button id="btnUseFetch" onclick="useFetch()" class="btn btn-danger">Use Fetch</button>

    <script type="text/javascript">
        function useFetch() {
            var loginParam = JSON.stringify({ email: 'hasan@gmail.com', pswd: '1234' });
            fetch('/api/Fetch', {  // or 'http://localhost:5000/api/Fetch' in external file
                method: 'post',
                headers: new Headers({
                    'Content-Type': 'application/json'
                }),
                body: loginParam
            }).then(function(response) {
                return response.json();
            }).then(function(returnedValue) {
                var asdf = returnedValue;
                console.log(asdf);
            }).catch(function (err) {
                console.log(JSON.stringify(err));
            });
        }
    </script>
</body>
</html>
Community
  • 1
  • 1
Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203