I've set up this test method on a controller to strip out any complication to it. Based off of all the results I've found from searching this should work. I'm not sure what I'm missing here.
public JsonResult test()
{
return Json(new { id = 1 });
}
This is the error I get.
Cannot implicitly convert type 'System.Web.Http.Results.JsonResult' to 'System.Web.Mvc.JsonResult'
you should return a JsonResult instead of just Json
public JsonResult test()
{
var result = new JsonResult();
result.Data = new
{
id = 1
};
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}
Try the following:
public System.Web.Http.Results.JsonResult test()
{
return Json(new { id = 1 });
}
It seems that Json does not generate a System.Web.Mvc.JsonResult which is expected as you are probably using System.Web.Mvc; but a System.Web.Http.Results.JsonResult.
The more generic one should also work:
public ActionResult test()
{
return Json(new { id = 1 });
}
NOTE:
In my MVC controllers the Json method does return a System.Web.Mvc.JsonResult. Are you inheriting from the default System.Web.Mvc.Controller?
Try
return Json(new { id = 1 }, JsonRequestBehavior.AllowGet);
You need to return the data through a model class rather than an anonymous class. Like:
public System.Web.Http.Results.JsonResult<modelClass> test(){
return Json(new modelClass(){ id=1 });
}
In MVC JsonResult is inherited from ActionResult which is in namespace System.Web.Mvc
thats why you should make the Reference to System.Web.Mvc.JsonResult as::
public System.Web.Mvc.JsonResult test()
{
return Json(new { id = 1 });
}
Put this in your Using:
using System.Web.Http.Results;
Then Your Action:
public JsonResult<YourClass> Get(string Search)
{
var Search = Search
return Json(Search);
}
Related
I've been trying to create methods where I use dapper's QueryMultiple. I've managed to get the multiple query to work, and when I debug I can see that the values from the database gets returned. However, I would like to see the data in Postman when calling the API. Here's where the problems start, since I can't seem to get any return type to work, it's almost always the same error. The error is almost always regarding "Cannot convert". Examples of errors are:
Error CS1503 Argument 1: cannot convert from 'string' to \RequestRepo.cs 45 Active
Error CS0266 Cannot implicitly convert type 'System.Collections.Generic.List<string>' to 'System.Collections.Generic.IEnumerable<V4ReactAPI.Models.V4RequestSite.ViewModels.RequestOverview>'. An explicit conversion exists (are you missing a cast?) 90 Active
The controller looks like:
[HttpGet]
public async Task<IActionResult> testa(RequestOverview model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
await _request.testa(model);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
return Ok();
}
The model:
public class VehicleReg
{
public string vehicleRegNr { get; set; } = "";
}
public class TestIgen
{
public string ownerName { get; set; } = "";
}
(Name of the whole model class is RequestOverview)
Now the method, which i have in an own class:
public async Task<IEnumerable<RequestOverview>> testa(RequestOverview model)
{
string query = "SELECT TOP 5 RegNumber as vehicleRegNr FROM [dbo].[Vehicle];
SELECT TOP 5 Name as ownerName FROM [dbo].[Customer];";
var result = _sqlconnection.QueryMultiple(query);
var vehicles = result.Read<VehicleReg>();
var test = result.Read<TestIgen>();
List<string> allQueries = new List<string>();
foreach (var item in vehicles)
{
allQueries.Add(item.vehicleRegNr);
}
foreach (var item in test)
{
allQueries.Add(item.ownerName);
return allQueries.ToList();
}
This throws an ERROR directly (The CS0266 as shown before).
Basically, I need to return the var vehicles and var test returned in some way, to be able to get the data to be shown when calling the api in postman for example.
I've also tried this method, but again I'm having trouble returning the data:
public async Task<bool> Test()
{
string query = "SELECT TOP 5 RegNumber as vehicleRegNr FROM [dbo].[Vehicle];
SELECT TOP 5 Name as ownerName FROM [dbo].[Customer];";
var result = _sqlconnection.QueryMultiple(query);
using (var multi = _sqlconnection.QueryMultiple(query, null))
{
List<VehicleReg> list1 = multi.Read<VehicleReg>().AsList();
List<TestIgen> list2 = multi.Read<TestIgen>().AsList();
}
return true;
}
Anyone have any ideas on how to return the data?
[Update] I have tried the following to avoid the converting error, but it's still not returning any data when I try it in Postman:
public async Task<List<string>> Test()
{
string query = "SELECT TOP 5 RegNumber as vehicleRegNr FROM [dbo].[Vehicle];
SELECT TOP 5 Name as ownerName FROM [dbo].[Customer];";
List<string> allQueries = new List<string>();
using (var multi = _sqlconnection.QueryMultiple(query, null))
{
//List<string> allQueries = new List<string>();
List<VehicleReg> list1 = multi.Read<VehicleReg>().AsList();
List<TestIgen> list2 = multi.Read<TestIgen>().AsList();
//return list1.ToList();
allQueries.Add(list1.ToString());
allQueries.Add(list2.ToString());
}
return allQueries;
}
If I understand correctly you want to return a list of vehicleRegNr and ownerName. So list1.ToString(); does not make any sense in that case since it is a type of List<VehicleReg>.
You need to select fields (vehicleRegNr from VehicleReg and ownerName from TestIgen) before adding to your allQueries.
So this
allQueries.Add(list1.ToString());
allQueries.Add(list2.ToString());
should be
allQueries.AddRange(list1.Select(i => i.vehicleRegNr));
allQueries.AddRange(list2.Select(i => i.ownerName));
And also if you want to return that value from API, you need to use OK with given result as follows:
[HttpGet]
public async Task<IActionResult> testa(RequestOverview model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
return Ok(await _request.testa(model);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
return Ok();
}
See ASP.NET Core return JSON with status code
I am building a simple MVC CRUD without using a database, but just making methods in a Repository model class.
To make it easier to understand i have 2 model classes. MyNote in which i have some properties and NoteRepository in which i have a list with the properties.
Then I've made a NoteController and i have already made Get and Create methods, but i can't seem to figure out what to write to make an Edit and Delete method? Hope you guys can help.
Here you will see some of the code from my project:
[HttpPost]
public ActionResult Create(MyNote mn)
{
try
{
note.Create(mn);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
this is the create from the Controller.
public static List<MyNote> notes = new List<MyNote>();
public NoteRepository()
{
notes.Add(new MyNote() { ID = 1, Titel = "Morgenmad", OprettelsesDato = DateTime.Now, Note = "Spis morgenmad i dag" });
notes.Add(new MyNote() { ID = 2, Titel = "Frokost", OprettelsesDato = DateTime.Now, Note = "Spis frokost i dag" });
notes.Add(new MyNote() { ID = 3, Titel = "Aftensmad", OprettelsesDato = DateTime.Now, Note = "Spis aftensmad i dag" });
}
public void Create(MyNote mn)
{
notes.Add(mn);
}
here is the repository class with the list and the method for the create method.
and please, ask if i have missed something! Thank you :-)
It looks like you're using a List for your in-memory repository. For delete, you can implement something like this:
public bool Delete (MyNote noteToDelete) {
return notes.Remove(noteToDelete);
}
Edit: However, in this case, the list will check for reference equality. Since you have an ID, which I will assume is unique, you can instead do this:
public bool Delete(MyNote noteToDelete) {
var matchingNote = notes.FirstOrDefault(n => n.ID == noteToDelete.ID);
return notes.Remove(matchingNote);
}
You could also implement IEquatable on your MyNote class to change how your notes are compared with each other, and return a valid match when the IDs are the same.
For the IEquatable example, you would want to change the class definition for MyNote to look like:
public class MyNote : IEquatable<MyNote>
and add in the following code to the MyNote class:
public override bool Equals(object obj) {
if (obj == null) return false;
Part objAsNote = obj as MyNote;
if (objAsNote == null) return false;
else return Equals(objAsNote);
}
public bool Equals(MyNote otherNote) {
if(otherNote == null) return false;
return (this.ID.Equals(otherNote.ID));
}
public override int GetHashCode(){
return this.ID;
}
You can do something like this:
public ActionResult Edit(MyNote noteToEdit)
{
var oldNote = notes.FirstOrDefault(n => n.Id == noteToEdit.Id);
if(oldNote == null)
return View(); //With some error message;
oldNote.Title = noteToEdit.Title;
oldNote.OprettelsesDato = DateTime.Now;
oldNote.Note = noteToEdit.Note;
return RedirectToAction("Index", "Note");
}
public ActionResult Delete(int id)
{
var noteToRemove = notes.FirstOrDefault(x => x.Id == id);
if(noteToRemove == null)
return View(); //With some error message;
notes.Remove(noteToRemove);
return RedirectToAction("Index", "Note");
}
When you are editing your note, i recommend you to use AutoMapper to make your code more easy to maintain.
I have this code in C# mvc Controller:
[HttpPost]
public ActionResult Delete(string runId)
{
if (runId == "" || runId == null)
{
return this.Json(new { error = "Null or empty params" });
}
try
{
int userId = (int)Session["UserId"];
int run = Convert.ToInt32(runId);
CloudMgr cloud = new CloudMgr(Session);
cloud.DeleteRun(userId, run);
return this.Json(new { success = true });
}
catch (Exception ex)
{
return this.Json(new { error = ex.ToString() });
}
}
How I can access my Json "error" field in a ControllerTest to check if it is null or not?
[TestMethod]
public void DeleteWrongParam()
{
WhatIfController controller = new WhatIfController();
controller.ControllerContext =
TestUtils.CreateMockSessionControllerContext().Object as ControllerContext;
JsonResult result = controller.DeleteWhatIf(null) as JsonResult;
Assert.IsNotNull(result.Data.error); is what I would like to do. Any Ideas? Thanks.
JavaScriptSerializer is good for string and static type. Here you created anonymous type as Json(new { success = true }). This case, you had better used dynamic type.
JsonResult result = controller.DeleteWhatIf(null) as JsonResult;
dynamic dresult = result.Data;
Assert.IsTrue(dresult.succes);
You need to import Microsoft.CSharp dll to test project.
If test and your controller are in different assemblies, you need to make the test assembly a "friend" assembly of the controller assembly, like this:
[assembly: InternalsVisibleTo("testproject assembly name")]
You can use like this - the result will be the expected object definition. So in case of success, your success flag will be TRUE otherwise false and if false then you should expect that the error property will be updated with the error message.
JsonResult jsonResult = oemController.List() as JsonResult;
JavaScriptSerializer serializer = new JavaScriptSerializer();
Result result = serializer.Deserialize<Result>(serializer.Serialize(jsonResult.Data));
public class Result
{
public bool success ;
public string error;
}
If you returned an actually non-anonymous class, you could have just done:
var strongTypedResult = result as <YourStrongTypeHere>;
I have a Backbone project where I have the following model that I want to pass on to .NET for database updating.
var myList = Backbone.Model.extend({
// Default attributes for the todo item.
defaults: function () {
return {
Name: "Default name"
};
},
url: "/my/myList",
"sync": mySyncFunction,
// Ensure that each todo created has `title`.
initialize: function () {
if (!this.get("Name")) {
this.set({ "Name": this.defaults.Name });
}
}
});
Using the following for overriding the sync
function mySyncFunction(method, model, options) {
if (method == 'GET') {
options.url = model.url;
}
else if (method == "create") {
options.url = model.url+"Post";
}
else {
options.url = model.url;
}
Backbone.emulateJSON = true
return Backbone.sync(method, model, options);
}
When creating a new item it is using the model.url+"Post" I assumed and the model.get("Name") contains the correct data. The correct section is executed and the entry in the database is created but the Name is empty.
Although when the .NET Controller handles the post the Name no longer contains any data.
My controller code looks like this.
public class myController : Controller
{
public ActionResult myList()
{
List<myCore.myList> l = new List<myCore.myList>();
l = myCore.myList.ListAll();
return Json(l, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public ActionResult myListPost(myCore.myList doc)
{
doc.AccountGuid = Guid.NewGuid();
Boolean created = doc.Create();
return Json(doc);
}
[HttpPut]
public ActionResult myListPut(myCore.myList doc)
{
myCore.myList doc1 = new myCore.myList();
doc1.AccountGuid = Guid.Empty;
doc1.Name = "testPut";
Boolean created = doc1.Create();
return Json(doc1);
}
[HttpDelete]
public ActionResult myListDelete(myCore.myList doc)
{
//DeleteDoc(id);
myCore.myList doc1 = new myCore.myList();
doc1.id = Guid.NewGuid();
doc1.AccountGuid = Guid.Empty;
doc1.Name = "testDelete";
Boolean created = doc1.Create();
return Json(doc1);
}
}
Can anyone tell me what to do to get the model/class data into the controller.
The myList class looks like this.
public class myList
{
Guid _id = Guid.Empty;
String _name = String.Empty;
Guid _accountGuid = Guid.Empty;
public Guid id
{
get { return _id; }
set { _id = value; }
}
public String Name
{
get { return _name; }
set { _name = value; }
}
public Guid AccountGuid
{
get { return _accountGuid; }
set { _accountGuid = value; }
}
}
UPDATE
It now looks like it works after removing Backbone.emulateJSON = true
Although I still cant get my delete part to work. It comes up with a 404 error. Only Post and Get works.
It looks like this in the controller.
[ActionName("myList")]
[HttpDelete]
public ActionResult myListDelete(myCore.myList doc)
{
doc.Name += "-DELETE";
return Json(doc);
}
UPDATE
Figured that one out as well.
ASP.NET Handle PUT/DELETE verbs
Although i can seem to pass any model or paramters along with it on order to delete the correct entry in the database.
Change your defaults to
defaults: {
Name: "Default name"
},
When using MVC, returning adhoc Json was easy.
return Json(new { Message = "Hello"});
I'm looking for this functionality with the new Web API.
public HttpResponseMessage<object> Test()
{
return new HttpResponseMessage<object>(new { Message = "Hello" }, HttpStatusCode.OK);
}
This throws an exception as the DataContractJsonSerializer can't handle anonymous types.
I have replaced this with this JsonNetFormatter based on Json.Net.
This works if I use
public object Test()
{
return new { Message = "Hello" };
}
but I don't see the point of using Web API if I'm not returning HttpResponseMessage, I would be better off sticking with vanilla MVC. If I try and use:
public HttpResponseMessage<object> Test()
{
return new HttpResponseMessage<object>(new { Message = "Hello" }, HttpStatusCode.OK);
}
It serializes the whole HttpResponseMessage.
Can anyone guide me to a solution where I can return anonymous types within a HttpResponseMessage?
This doesn't work in the Beta release, but it does in the latest bits (built from http://aspnetwebstack.codeplex.com), so it will likely be the way for RC. You can do
public HttpResponseMessage Get()
{
return this.Request.CreateResponse(
HttpStatusCode.OK,
new { Message = "Hello", Value = 123 });
}
This answer may come bit late but as of today WebApi 2 is already out and now it is easier to do what you want, you would just have to do:
public object Message()
{
return new { Message = "hello" };
}
and along the pipeline, it will be serialized to xml or json according to client's preferences (the Accept header). Hope this helps anyone stumbling upon this question
In web API 2 you can use the new IHttpActionResult which is a replacement for HttpResponseMessage and then return a simple Json object: (Similiar to MVC)
public IHttpActionResult GetJson()
{
return Json(new { Message = "Hello"});
}
you can use JsonObject for this:
dynamic json = new JsonObject();
json.Message = "Hello";
json.Value = 123;
return new HttpResponseMessage<JsonObject>(json);
You could use an ExpandoObject. (add using System.Dynamic;)
[Route("api/message")]
[HttpGet]
public object Message()
{
dynamic expando = new ExpandoObject();
expando.message = "Hello";
expando.message2 = "World";
return expando;
}
You may also try:
var request = new HttpRequestMessage(HttpMethod.Post, "http://leojh.com");
var requestModel = new {User = "User", Password = "Password"};
request.Content = new ObjectContent(typeof(object), requestModel, new JsonMediaTypeFormatter());
In ASP.NET Web API 2.1 you can do it in a simpler way:
public dynamic Get(int id)
{
return new
{
Id = id,
Name = "X"
};
}
You can read more about this on https://www.strathweb.com/2014/02/dynamic-action-return-web-api-2-1/
public IEnumerable<object> GetList()
{
using (var context = new DBContext())
{
return context.SPersonal.Select(m =>
new
{
FirstName= m.FirstName ,
LastName = m.LastName
}).Take(5).ToList();
}
}
}
You should be able to get this to work if you use generics, as it will give you a "type" for your anonymous type. You can then bind the serializer to that.
public HttpResponseMessage<T> MakeResponse(T object, HttpStatusCode code)
{
return new HttpResponseMessage<T>(object, code);
}
If there are no DataContract or DataMebmer attributes on your class, it will fall back on serializing all public properties, which should do exactly what you're looking for.
(I won't have a chance to test this until later today, let me know if something doesn't work.)
You can encapsulate dynamic object in returning object like
public class GenericResponse : BaseResponse
{
public dynamic Data { get; set; }
}
and then in WebAPI; do something like:
[Route("api/MethodReturingDynamicData")]
[HttpPost]
public HttpResponseMessage MethodReturingDynamicData(RequestDTO request)
{
HttpResponseMessage response;
try
{
GenericResponse result = new GenericResponse();
dynamic data = new ExpandoObject();
data.Name = "Subodh";
result.Data = data;// OR assign any dynamic data here;//
response = Request.CreateResponse<dynamic>(HttpStatusCode.OK, result);
}
catch (Exception ex)
{
ApplicationLogger.LogCompleteException(ex, "GetAllListMetadataForApp", "Post");
HttpError myCustomError = new HttpError(ex.Message) { { "IsSuccess", false } };
return Request.CreateErrorResponse(HttpStatusCode.OK, myCustomError);
}
return response;
}