Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 days ago.
Improve this question
I'm trying to create random values and send them to controller which is in mvc api controller.But my datas in api always come 0 or null like their default. In console app i'm creating them but my datas come null or 0. What is my real problem?
My console code:
using MSE.DTO.DTOs.WorkStation;
using Newtonsoft.Json;
using System.Net.Http.Json;
using System.Text;
var random = new Random(DateTime.Now.Millisecond);
var data = new WorkStationRandomValueDTO
{
WorkStationId = random.Next(1, 100),
Temperature = (decimal)Math.Round(random.NextDouble() * 100, 2),
Pressure = (decimal)Math.Round(random.NextDouble() * 2000, 2),
Status = random.Next(0, 1) == 1
};
using (var client = new HttpClient())
{
var content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var response = await client.PostAsync("http://localhost:5002/WorkStationRandom/Post", content);
if (response.IsSuccessStatusCode)
{
Console.WriteLine($"WorkStationId: {data.WorkStationId}\nTemperature: {data.Temperature}\nPressure: {data.Pressure}\nStatus: {data.Status}\n ");
Console.WriteLine("Data posted successfully");
}
else
{
Console.WriteLine("Error occured while posting data");
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
Console.ReadLine();
My Mvc Api Code :
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using MSE.DataAccess.Context;
using MSE.DTO.DTOs.WorkStation;
using MSE.Entity.Entities.Concrete;
using FromBodyAttribute = System.Web.Http.FromBodyAttribute;
using HttpGetAttribute = System.Web.Http.HttpGetAttribute;
using HttpPostAttribute = System.Web.Http.HttpPostAttribute;
namespace MSE.Web.Controllers
{
public class WorkStationRandomController : ControllerBase
{
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
public WorkStationRandomController(ApplicationDbContext dbContext, IMapper mapper)
{
_dbContext = dbContext;
_mapper = mapper;
}
[HttpPost]
public IActionResult Post([FromBody] WorkStationRandomValueDTO data)
{
if (data != null && data.WorkStationId != 0 && data.Temperature != 0 && data.Pressure != 0)
{
data.Status = true;
var workStation = _mapper.Map<WorkStation>(data);
_dbContext.WorkStations.Add(workStation);
_dbContext.SaveChanges();
return Ok();
}
else
{
return BadRequest("Data is not valid.");
}
}
[HttpGet]
public string Get()
{
return "ok";
}
}
}
In this picture you can see my problem.
Thank you.
My point is that which create random values in console and send them to controller. But i always got 0 or null values.
I'm trying to create random values and send them to controller which
is in mvc api controller.But my datas in api always come 0 or null
like their default. In console app i'm creating them but my datas come
null or 0. What is my real problem?
Well, couple of things might cause you getting null data on your controller, first of all as #Serge point out that in your code you have used [FromBody] but your screenshot missing it. My take on this, request should reach to your controller if you build it with valid class property and with no additional configuration on your AddJsonOptions at your program.cs file according to your shared code snippet.
Correct Request Format Based On Your Shared Code:
Console App Snippet:
using Newtonsoft.Json;
using System.Text;
var random = new Random(DateTime.Now.Millisecond);
var data = new WorkStationRandomValueDTO
{
WorkStationId = random.Next(1, 100),
Temperature = (decimal)Math.Round(random.NextDouble() * 100, 2),
Pressure = (decimal)Math.Round(random.NextDouble() * 2000, 2),
Status = random.Next(0, 1) == 1
};
using (var client = new HttpClient())
{
var content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var response = await client.PostAsync("http://localhost:5094/WorkStationRandom/post", content);
if (response.IsSuccessStatusCode)
{
Console.WriteLine($"WorkStationId: {data.WorkStationId}\nTemperature: {data.Temperature}\nPressure: {data.Pressure}\nStatus: {data.Status}\n ");
Console.WriteLine("Data posted successfully");
}
else
{
Console.WriteLine("Error occured while posting data");
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
public class WorkStationRandomValueDTO
{
public int WorkStationId { get; set; }
public decimal Temperature { get; set; }
public decimal Pressure { get; set; }
public bool Status { get; set; }
}
API Code Snippet:
public class WorkStationRandomController : ControllerBase
{
[HttpPost]
public IActionResult Post([FromBody] WorkStationRandomValueDTO data)
{
if (data != null && data.WorkStationId != 0 && data.Temperature != 0 && data.Pressure != 0)
{
//data.Status = true;
//var workStation = _mapper.Map<WorkStation>(data);
//_dbContext.WorkStations.Add(workStation);
//_dbContext.SaveChanges();
return Ok();
}
else
{
return BadRequest("Data is not valid.");
}
}
}
public class WorkStationRandomValueDTO
{
public int WorkStationId { get; set; }
public decimal Temperature { get; set; }
public decimal Pressure { get; set; }
public bool Status { get; set; }
}
Output:
Note:
Any additional, configurations which has not been shared will not be considered here.
Why Then Yours One Not Working:
1. If you have any configuration in program.cs which has not shared
with us:
If you follow my above sample, your request should reach to your controller with valid data as you can see in given debug capture. In this scenario you do not need builder.Services.AddControllersWithViews().AddJsonOptions(options => on your program.cs file.
For instance: If you have any additional property on your AddJsonOptions which you haven't shared that also might cuase the issue.
2. If you define WorkStationRandomValueDTO as Property as Field
Inside your WorkStationRandomValueDTO class if you define WorkStationId, Temperature and others member as Fields just as following:
public class WorkStationRandomValueDTO
{
public int WorkStationId;
public decimal Temperature;
public decimal Pressure;
public bool Status;
}
Fields instead of Property might cause null data in your controller as per your shared code. It doesn't mean that you cannot send field value but the way you are sending request at this moment that cause null parameter.
Therefore, above two issue can cause your empty reuqest at your controller. Here I have the reproduce your scenario accordingly.
Issue Reproduced With Null Parameter:
Related
I am pulling data from API. I am getting an error while deserializing. please help me.
error:
System.Text.Json.JsonException: '',' is invalid after a single JSON value. Expected end of data. Path: $ | LineNumber: 0 | BytePositionInLine: 128.'
data i pull:
{"firmano":128257,"adi":"- FATİH YILMAZ"},{"firmano":128446,"adi":"-MEHMET ÜSTÜN"}
my c# codes:
Index.cs :
var result = await Api<Company>.pullDataAsync("https://localhost:5001/api/PesinIskontolar/companyGet");
api.cs:
public class Api<T> where T : class
{
public async static Task<T> pullDataAsync(string url)
{
var client = new RestClient(url);
var request = new RestRequest(Method.GET);
IRestResponse response = await client.ExecuteAsync(request);
return Json_Convert<T>.deserializeProcess(apiFormat(response.Content));
}
public static string apiFormat(string response)
{
var result = response.Replace("\\", "").Replace("[","").Replace("]","");
return result.Substring(1, result.Length - 2);
}
}
Json_Convert.cs:
public class Json_Convert<T> where T : class
{
public static T deserializeProcess(string response)
{
return JsonSerializer.Deserialize<T>(response);
}
}
dal:
public string getCompany()
{
......
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
string data = JsonConvert.SerializeObject(dt);
baglanti.Close();
baglanti.Dispose();
return data;
}
api:
[HttpGet("companyGet")]
public IActionResult companyGet()
{
return Ok(_firmaServices.getCompany());
}
Since some friends said that there is a problem with the api, I added other codes.
company class:
public class Company
{
public int firmano { get; set; }
public string adi { get; set; }
}
Your JSON is invalid, should be:
[{"firmano":128257,"adi":"- FATİH YILMAZ"},{"firmano":128446,"adi":"-MEHMET ÜSTÜN"}]
instead of:
{"firmano":128257,"adi":"- FATİH YILMAZ"},{"firmano":128446,"adi":"-MEHMET ÜSTÜN"}
Also, instead of calling response.Content prior to deserialization, you need to call await response.Content.ReadAsStringAsync() method to actually read the returning json string from the server.
As you pulling a list of two companies, your deserialization should be deserializing to a list instead of a single object, so you need to delete the apiFormat method and call await Api<IEnumerable<Company>>.pullDataAsync instead of await Api<Company>.pullDataAsync
You should deserialize List< Company >, not just Company so use this code
var result = await Api<List<Company>>.pullDataAsync("https://localhost:5001/api/PesinIskontolar/companyGet");
and fix your generic code by removing apiFormat(response.Content), replace it by just content. it will prevent removing [] from your json, this is what causes an exception
public async static Task<T> pullDataAsync(string url)
{
var client = new RestClient(url);
var request = new RestRequest(Method.GET);
IRestResponse response = await client.ExecuteAsync(request);
return Json_Convert<T>.deserializeProcess(response.Content); //fix here!!!
}
and according to your response.Content, you company class should be changed
public partial class Company
{
[JsonPropertyName("firmano")]
public int firmano { get; set; }
[JsonPropertyName("Column1")]
public string adi { get; set; }
}
1.Try to use known class as Company instate of
2.Json converter does not like special characters like '(Some times People are using the ' char, to write a letter like è, and this can bracke the Json String). You can do like .Replace("'", "''")
3.Use encoding UTF8.
4.Control the API Site in Debug and see the Response creation..
5. before subtracting the end 2 chars check if the string has this chars. better do this operations after you get the response.
return result.Substring(1, result.Length - 2);
i have transform a php/js code to js/c#, but i stuck for update the new value.
The php code is :
`if (isset($_POST['update'])) {
foreach($_POST['positions'] as $position) {
$index = $position[0];
$newPosition = $position[1];
$conn->query("UPDATE country SET position = '$newPosition' WHERE id='$index'");
}
exit('success');
}`
My "empty" c# code
[HttpPost]
public ActionResult Index (userTable index)
{
picturesEntities MyDb = new picturesEntities();
homeViewModel HVM = new homeViewModel();
HVM.userTables = MyDb.userTables.ToList();
if (Request["update"] != null)
{
foreach (Request["positions"])
{
MyDb.SaveChanges();
}
return View(HVM);
}
}
If someone could help me for it that would be great, i'm stuck on it for days and i didn't find a workning solution yet.
Thanks to everyone who read my message.
Most ASP.NET will bind a custom class which will be compatible to your request.
public class UserPositionsRequest
{
public bool Update { get; set; }
// For orderly, this actually be a list of a custom class
public List<int[]> Positions { get; set; }
}
This by any means is not a complete and working solution, the following code was never been tested and can be consider as pseudo-like code.
Also, the .Id and .Position should be the same sensitivity as in Db.
// Binding our UserPositionsRequest class
public void Index(UserPositionsRequest request) {
// Checking if we should update, if you will change the request to boolean type: "true"
// ..on the client side, then you could actually change the condition to be: if (request.Update)
if (request.Update == 1) {
// Creating database connection using (I assume) EntityFramework
using (var picturesEntities = new picturesEntities()) {
// Building a dictionary for fast lookup. Key, Value as the 0, 1 arg respectfully
var usersDataToUpdate = request.Positions.ToDictionary(p => p[0], p => p[1]);
// Finding the entries that needs to be updated
var usersEntitiesToUpdate = picturesEntities.userTables.Where(cntry => usersDataToUpdate.ContainsKey(cntry.Id));
// Iterating over the entities
foreach (var userEntity in usersEntitiesToUpdate) {
// Updating their position.
userEntity.Position = usersDataToUpdate[userEntity.Id];
}
picturesEntities.SaveChanges();
}
}
// Probably you wanted to return something here, but it's probably an ajax and you can skip that.
}
I develop web service of android app with asp.net web api
In android we have to program : users and stores
stores should see last user request in their app
for example I am users and I want to buy some things like rice , after I send my request to server it's save in database. after that stores that are near my location should see my request
My problem is how can I check new user request and send them to stores in real time?
should I use signalR? id yes how?
note: I wrote algoritm of get near store and I just have problem in how to send
my example code:
using System;
using System.Collections.Generic;
using System.Device.Location;
using System.Globalization;
using System.Linq;
using WebService.Models.Domain;
using Microsoft.AspNet.SignalR;
namespace WebService
{
public class MyHub : Hub
{
private readonly mydb db = new mydb();
public void Send(string storeToken)
{
try
{
if (storeToken != null)
{
......
......
......
if (distanceInMeter < maxStoreDistance)
{
var obj = new GetBuy
{
buy = new AllBuy
{
id = newBuyRequest.Id,
longitude = newBuyRequest.longitude ?? 0,
latitude = newBuyRequest.latitude ?? 0,
time = Convert.ToString(newBuyRequest.time, CultureInfo.InvariantCulture),
price = newBuyRequest.price ?? 0,
distanceInMeter = distanceInMeter
}
};
resultList.Add(obj.buy);
}
Clients.All.sendToShop(resultList);
}
}
Clients.All.sendToShop("error");
}
catch (Exception)
{
Clients.All.sendToShop("error");
}
}
//************************************
private class GetBuy
{
public AllBuy buy;
}
private class AllBuy
{
public int id;
public double longitude;
public double latitude;
public string time;
public double price;
public double distanceInMeter;
}
}
}
My 1st question, so please be kind... :)
I'm using the C# HttpClient to invoke Jobs API Endpoint.
Here's the endpoint: Jobs API Endpoint (doesn't require key, you can click it)
This gives me JSON like so.
{
"count": 1117,
"firstDocument": 1,
"lastDocument": 50,
"nextUrl": "\/api\/rest\/jobsearch\/v1\/simple.json?areacode=&country=&state=&skill=ruby&city=&text=&ip=&diceid=&page=2",
"resultItemList": [
{
"detailUrl": "http:\/\/www.dice.com\/job\/result\/90887031\/918715?src=19",
"jobTitle": "Sr Security Engineer",
"company": "Accelon Inc",
"location": "San Francisco, CA",
"date": "2017-03-30"
},
{
"detailUrl": "http:\/\/www.dice.com\/job\/result\/cybercod\/BB7-13647094?src=19",
"jobTitle": "Platform Engineer - Ruby on Rails, AWS",
"company": "CyberCoders",
"location": "New York, NY",
"date": "2017-04-16"
}
]
}
I've pasted a complete JSON snippet so you can use it in your answer. The full results are really long for here.
Here's are the C# classes.
using Newtonsoft.Json;
using System.Collections.Generic;
namespace MyNameSpace
{
public class DiceApiJobWrapper
{
public int count { get; set; }
public int firstDocument { get; set; }
public int lastDocument { get; set; }
public string nextUrl { get; set; }
[JsonProperty("resultItemList")]
public List<DiceApiJob> DiceApiJobs { get; set; }
}
public class DiceApiJob
{
public string detailUrl { get; set; }
public string jobTitle { get; set; }
public string company { get; set; }
public string location { get; set; }
public string date { get; set; }
}
}
When I invoke the URL using HttpClient and deserialize using JSON.NET, I do get the data back properly.
Here's the code I am calling from my Console App's Main method (hence the static list, I think this could be better refactored??)
private static List<DiceApiJob> GetDiceJobs()
{
HttpClient httpClient = new HttpClient();
var jobs = new List<DiceApiJob>();
var task = httpClient.GetAsync("http://service.dice.com/api/rest/jobsearch/v1/simple.json?skill=ruby")
.ContinueWith((taskwithresponse) =>
{
var response = taskwithresponse.Result;
var jsonString = response.Content.ReadAsStringAsync();
jsonString.Wait();
var result = JsonConvert.DeserializeObject<DiceApiJobWrapper>(jsonString.Result);
if (result != null)
{
if (result.DiceApiJobs.Any())
jobs = result.DiceApiJobs.ToList();
if (result.nextUrl != null)
{
//
// do this GetDiceJobs again in a loop? How?? Any other efficient elegant way??
}
}
});
task.Wait();
return jobs;
}
But now, how do I check if there are more jobs using the nextUrl field? I know I can check to see if it's not null, and if if not, that means there are more jobs to pull down.
Results from my debugging and stepping through
How do I do this recursively, and without hanging and with some delays so I don't cross the API limits? I think I have to use TPL ( Task Parallel Library) but am quite baffled.
Thank you!
~Sean
If you are concerned about response time of your app and would like to return some results before you actually get all pages/data from the API, you could run your process in a loop and also give it a callback method to execute as it gets each page of data from the API.
Here is a sample:
public class Program
{
public static void Main(string[] args)
{
var jobs = GetDiceJobsAsync(Program.ResultCallBack).Result;
Console.WriteLine($"\nAll {jobs.Count} jobs displayed");
Console.ReadLine();
}
private static async Task<List<DiceApiJob>> GetDiceJobsAsync(Action<DiceApiJobWrapper> callBack = null)
{
var jobs = new List<DiceApiJob>();
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("http://service.dice.com");
var nextUrl = "/api/rest/jobsearch/v1/simple.json?skill=ruby";
do
{
await httpClient.GetAsync(nextUrl)
.ContinueWith(async (jobSearchTask) =>
{
var response = await jobSearchTask;
if (response.IsSuccessStatusCode)
{
string jsonString = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<DiceApiJobWrapper>(jsonString);
if (result != null)
{
// Build the full list to return later after the loop.
if (result.DiceApiJobs.Any())
jobs.AddRange(result.DiceApiJobs.ToList());
// Run the callback method, passing the current page of data from the API.
if (callBack != null)
callBack(result);
// Get the URL for the next page
nextUrl = (result.nextUrl != null) ? result.nextUrl : string.Empty;
}
}
else
{
// End loop if we get an error response.
nextUrl = string.Empty;
}
});
} while (!string.IsNullOrEmpty(nextUrl));
return jobs;
}
private static void ResultCallBack(DiceApiJobWrapper jobSearchResult)
{
if (jobSearchResult != null && jobSearchResult.count > 0)
{
Console.WriteLine($"\nDisplaying jobs {jobSearchResult.firstDocument} to {jobSearchResult.lastDocument}");
foreach (var job in jobSearchResult.DiceApiJobs)
{
Console.WriteLine(job.jobTitle);
Console.WriteLine(job.company);
}
}
}
}
Note that the above sample allows the callback method to access each page of data as it is received by the GetDiceJobsAsync method. In this case, the console, displays each page as it becomes available. If you do not want the callback option, you can simply pass nothing to GetDiceJobsAsync.
But the GetDiceJobsAsync also returns all the jobs when it completes. So you can choose to act on the whole list at the end of GetDiceJobsAsync.
As for reaching API limits, you can insert a small delay within the loop, right before you repeat the loop. But when I tried it, I did not encounter the API limiting my requests so I did not include it in the sample.
I'm using a custom JsonpResult class that I found in my searching here on SO. I've read through the code and I understand how it works (at least I think I do), BUT... for some reason when I serialize my Object, I'm getting duplicate strings... Why would this be?
Here's the custom class
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Content of this class was mostly derived from the original
* JsonResult class in the System.Web.Mvc 2.0 RTM Assembly. This
* has beeen slightly extended for use with JSONP calls.
*
* This software is subject to the Microsoft Public License (Ms-PL).
* A copy of the license can be found in the license.htm file included
* in this distribution.
*
* You must not remove this notice, or any other, from this software.
*
* ***************************************************************************/
namespace System.Web.Mvc
{
using System;
using System.Text;
using System.Web;
using System.Web.Mvc.Resources;
using System.Web.Script.Serialization;
public class JsonpResult : ActionResult
{
public JsonpResult() { }
public Encoding ContentEncoding { get; set; }
public string ContentType { get; set; }
public object Data { get; set; }
public string JsonCallback { get; set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
this.JsonCallback = context.HttpContext.Request["jsoncallback"];
if (string.IsNullOrEmpty(this.JsonCallback))
this.JsonCallback = context.HttpContext.Request["callback"];
if (string.IsNullOrEmpty(this.JsonCallback))
throw new ArgumentNullException("JsonCallback required for JSONP response.");
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
{
response.ContentType = ContentType;
}
else
{
response.ContentType = "application/javascript";
}
if (ContentEncoding != null)
{
response.ContentEncoding = ContentEncoding;
}
if (Data != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
response.Write(string.Format("{0}({1});", this.JsonCallback, serializer.Serialize(Data)));
}
}
}
//extension methods for the controller to allow jsonp.
public static class ContollerExtensions
{
public static JsonpResult Jsonp(this Controller controller, object data)
{
JsonpResult result = new JsonpResult();
result.Data = data;
result.ExecuteResult(controller.ControllerContext);
return result;
}
}
}
Here's my Controller Action
public class VimeoController : Controller
{
//
// GET: /Vimeo/
public JsonpResult Read()
{
Models.ViewModels.JsonViewModel JsonResponse;
try
{
VimeoSharp.APIs.VimeoSimple VimeoSimple = new VimeoSharp.APIs.VimeoSimple();
// Tell VimeoSharp what channel to pull it's videos from (193328)
List<VimeoSharp.Video> VimeoList = VimeoSimple.ChannelVideos("193328");
// Create a viewmodel list of videos to be used.
// we're only using id and title for this bit.
List<Models.Pocos.Vimeo> videoList = new List<Models.Pocos.Vimeo>();
foreach (VimeoSharp.Video record in VimeoList)
{
videoList.Add(new Models.Pocos.Vimeo
{
id = 1, //Int32.Parse(record.ID),
title = "a" //(record.Title.Length > 26 ? record.Title.Substring(0, 25) + "..." : record.Title)
});
};
JsonResponse = new Models.ViewModels.JsonViewModel
{
results = videoList,
success = true
};
}
catch {
JsonResponse = new Models.ViewModels.JsonViewModel
{
results = null,
success = false
};
}
// a failed response
return this.Jsonp(JsonResponse);
}
}
And here's the output result.
CALLBACK1001({"results":[{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"}],"success":true});CALLBACK1001({"results":[{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"},{"id":1,"title":"a"}],"success":true});
Why on earth is my JsonResponse being serialized twice?
The problem is in your extension method:
public static class ContollerExtensions
{
public static JsonpResult Jsonp(this Controller controller, object data)
{
JsonpResult result = new JsonpResult();
result.Data = data;
//result.ExecuteResult(controller.ControllerContext); <-- Remove this !!!
return result;
}
}
Notice the line I commented. You are basically invoking the result twice. It's the ASP.NET MVC framework's responsibility to invoke the ExecuteResult method on the ActionResult, not yours.
Also if you found this code on StackOverflow why is it Copyright (c) Microsoft Corporation. All rights reserved. :-)