Web Method not returning list? - c#

I have a .aspx page which I would like my WebMethod to return a List so I can call it from a jQuery ajax call and get a JSON type response... Here is my code but it just returns a blank page?
Any help would be great
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Services;
using System.Data.SqlClient;
using System.Configuration;
using System.Data;
using System.Web.Services.Protocols;
using System.Web.Script.Services;
namespace Test.webservices.mainGrid
{
public partial class staffTreeView : System.Web.UI.Page
{
[WebMethod()]
public static List<Staff> GetStaff()
{
try
{
List<Staff> staff = new List<Staff>();
// HttpCookie _userinfo = HttpContext.Current.Request.Cookies["userinfo"];
string connectionstring = ConfigurationManager.ConnectionStrings["TestProduction"].ConnectionString;
SqlConnection connection = new SqlConnection(connectionstring);
string sql = "sd_STAFFTREEVIEW";
SqlCommand command = new SqlCommand(sql, connection);
command.CommandType = CommandType.StoredProcedure;
SqlDataReader dr = command.ExecuteReader();
while (dr.Read())
{
staff.Add(new Staff()
{
id = dr.GetString(dr.GetOrdinal("id")),
NAME = dr.GetString(dr.GetOrdinal("NAME")),
PARENT = dr.GetString(dr.GetOrdinal("PARENT")),
VALUE = dr.GetString(dr.GetOrdinal("VALUE")),
VALUETYPE = dr.GetString(dr.GetOrdinal("VALUETYPE"))
});
}
dr.Close();
return staff;
}
catch (Exception ex)
{
throw new System.Exception("No Data Returned:" + ex.Message);
}
}
public class Staff
{
public string id { get; set; }
public string NAME { get; set; }
public string PARENT { get; set; }
public string VALUE { get; set; }
public string VALUETYPE { get; set; }
}
}
}

I would try changing the return type to a string and returning a json serialized string of the object.
Like this
JavaScriptSerializer js = new JavaScriptSerializer();
string strJSON = js.Serialize(staff);
return strJSON;

create a WCF service instead of a page !
and consider returning an Array instead of a generic list Staff[]

Few things to check.
Do you need to enable the session : Services.WebMethod(EnableSession:=True)
Are you using the correct method name ( check spelling). Better , could you post the code for ajax call ?
If you call the web method from somewhere else like code behind , is it giving you the correct result?

I would recommend that you use a WebAPI controller for this task, can be used in a web forms application, just wire up the routing in application_start
It will save you some pain and make your life easier
http://www.asp.net/web-api/overview/creating-web-apis/using-web-api-with-aspnet-web-forms

I suspect that your ajax call is not happening.
Provided you are sure that your list is not empty, make sure that you have set the dataType and contentType of your ajax request to json and "application/json" respectively.
If you are using a script manager control make sure Enablepagemethods is set to true.
finally you can try setting a break point in your error callback to find if there are any serialisation errors.if so, you can try to serialise the LIST to JSON using JavaScriptSerializer and return the result as String

Related

C# ASP.NET | Is there any point in me using a model class when saving data to MongoDB?

I have begun writing an ASP.NET Web API for an app that I am building. I have set up a MongoCRUD.cs class to save data from POST requests made by the app to a MongoDB database (and other CRUD actions).
I (following a beginner tutorial), also set up a Submission.cs model class to act as a blueprint for the objects I wanted to save to the database. However, now that I have implemented the InsertRecord() method in MongoCRUD.cs, I cannot see a use for this model.
MongoCRUD.cs:
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebAPI.Services
{
public class MongoCRUD
{
private IMongoDatabase db;
public MongoCRUD(string database)
{
var client = new MongoClient();
db = client.GetDatabase(database);
}
public void InsertRecord<T>(string table, T record)
{
var collection = db.GetCollection<T>(table);
collection.InsertOne(record);
}
}
}
Submission.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Web;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace WebAPI.Models
{
public class Submission
{
[BsonId]
public string SubId { get; set; }
public string Url { get; set; }
public string Text { get; set; }
}
}
SubmissionsController.cs:
using WebAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebAPI.Services;
using System.IO;
using System.Web.Script.Serialization;
namespace WebAPI.Controllers
{
public class SubmissionsController : ApiController
{
MongoCRUD db = new MongoCRUD("myDb");
Submission[] submission = new Submission[] {
new Submission { SubId = "test", Url = "test", Text = "test" };
};
public IEnumerable<Submission> GetAllSubmissions()
{
//add MongoCRUD functionality for load record
return submission;
}
public IHttpActionResult GetSubmission(string id)
{
//add MongoCRUD functionality for load record
return Ok();
}
public IHttpActionResult PostSubmission(object body)
{
//validate body
db.InsertRecord("Submissions", body);
return Ok();
}
}
}
As you can see at PostSubmission(), the body of the POST request can be saved to the database directly, so my question is what is the benefit of using a model such as Submission.cs instead of just using the object type?
I'm having some trouble traversing the body object to access its values (for carrying out validation etc), so my only guess is that using a model makes it easier to access values?
object is the base type for all classes (See - https://learn.microsoft.com/en-us/dotnet/api/system.object?view=netcore-3.1).
C# is an object-orientated language so we try to model classes based on our business domain, this makes it easier to reason about the code.
Like you said you can have models that can be used to validate the incoming data into the controller, also you might want to add extra methods on the models that related to your business domain.
For example
class CreditCard
{
string CardNumber { get;set; }
string Csv { get;set; }
bool ValidateChecksum()
{ }
}

Read argument is C#

I am trying to read parameters from URL in C# based Controller. But its giving error. I have copied the code and screen shot of the error.
In this code I am trying to read argument from url that is "hello":
using AxureAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace AxureAPI.Controllers
{
public class YNAController : ApiController
{
public ProjectDetails[] Get()
{
string value = Request.QueryString["hello"];
return new ProjectDetails[]
{
new ProjectDetails
{
Id = 1,
Name = "Prj1",
SvnPath = "svnPath1"
},
new ProjectDetails
{
Id = 2,
Name = "Prj2",
SvnPath = "svnPath2"
}
};
}
}
}
You cannot access the query string in WebAPI like that. Instead, it's much cleaner and simpler to let the MVC framework do the work for you and pass it in as a parameter. Change your controller method to this for example, so instead of using QueryString["hello"] you can access the parameter directly:
public ProjectDetails[] Get(string hello)
{
//Now do something with the parameter 'hello'
var whatever = "hello " + hello;
}
Now you can call your API like this:
http://server/api/YNA/Get?hello=fred
try this :
var query = message.RequestUri.ParseQueryString();
string key = query["Hello"];

C# JSON.net - Trying to deserialize JSON into C# results in correct number of objects but no properties set

I'm working on a custom add in for excel, I want it to get a list of projects from a remote web service. The JSON is coming back from the web servive to excel, but I'm having trouble turning the JSON into objects in C#.
Here is the AddIn code:
using Microsoft.Office.Tools.Ribbon;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Web;
namespace TestAddIn
{
class Project
{
static string currentProject;
static List<Project> validProjects;
public int id { get; set; }
public string name { get; set; }
public int svar_reserved_space { get; set; }
// Set the current project we're working on
internal static void setCurrentProject(string path)
{
Match match = Regex.Match(path, #"^[A-Za-z]:\\(\w+)");
Project.currentProject = match.Groups[1].Value;
foreach (Project validProject in validProjects)
{
RibbonDropDownItem dropDown = Globals.Ribbons.Ribbon1.Factory.CreateRibbonDropDownItem();
dropDown.Label = validProject.name;
if (validProject.name.Equals(Project.currentProject))
{
Globals.Ribbons.Ribbon1.projectComboBox.Items.Add(dropDown);
}
}
}
// Connect to a web service and get a list of valid projects
internal static void getValidProjects()
{
string url = "http://192.168.118.128/projects/json";
WebRequest webRequest;
webRequest = WebRequest.Create(url);
Stream objStream;
objStream = webRequest.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string sLine = objReader.ReadLine();
Debug.WriteLine("begin: " + sLine);
validProjects = JsonConvert.DeserializeObject<List<Project>>(sLine);
Debug.WriteLine("end");
}
}
}
When using this json:
[{"Project":{"id":1,"name":"test1","svar_reserved_space":2}},{"Project":{"id":2,"name":"test2","svar_reserved_space":0}}]
I get two Project objects in validProjects but the id and svar_reserver_space are 0, and the name is null. Thoguhts?
This is the easiest with some addins/nuget magic:
Install web essentials in Visual studio
Add the nuget package newtonsoft.json
Copy the JSON output string
Paste JSON as class
And use this code:
WebClient wc = new WebClient();
string json = wc.DownloadString("http://192.168.118.128/projects/json");
var a = JsonConvert.DeserializeObject<YourGeneratedMainClass>(json);
Where YourGeneratedMainClass is a class generated by pasting the json as classes.
If you use the method above, you will probably see that it has a parent object
public class Project
{
public int id { get; set; }
public string name { get; set; }
public int svar_reserved_space { get; set; }
}
public class Parent
{
public Project Project { get; set; }
}
More about it in these two S.O. questions:
Json.net deseralize to a list of objects in c# .net 2.0
Deserialized Object Has All Values Set to Null
I would suspect you need the JSON to look like:
[{"id":1,"name":"test1","svar_reserved_space":2},{"id":2,"name":"test2","svar_reserved_space":0}]
In order to use the default Json deserialization.

how to create a custom JSON in C# and what should the return value be?

i want create a custom json data from the mssql 2008 results so that my iPhone could consume it.
i can consume json websites like this without a problem:
json link
the format could look like this:
Place: New York
Hotel: Widget Hotel
Telephone: 0305525253
which format should i return to consume it on the iPhone? an array a string, dictionary? i don't know
EDIT: here is my code:
namespace WebService1
{
public class LandHelper
{
internal static string[] Land()
{
List<string> landObject = new List<string>();
using (SqlConnection con = new SqlConnection(#"Data Source=Localhost\SQLEXPRESS;Initial Catalog=BOOK-IT-V2;Integrated Security=true;"))
using (SqlCommand cmd = new SqlCommand(#"SELECT BEZEICHNUNG FROM LAND", con))
{
con.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
if (rdr["BEZEICHNUNG"] != DBNull.Value)
{
landObject.Add(rdr["BEZEICHNUNG"].ToString());
}
}
}
}
return landObject.ToArray();
}
}
}
i tried this but i don't know how to add a key to the values i get from the database.
i think it would be easier when i create a custom json format .
Just Return a List like
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
[WebMethod]
public List<StandortHelper.REGION> LAND()
{
return StandortHelper.LAND();
}
You can return easy a JSON-FORMAT
Okay, if I've understood this correctly what you're trying to do is stringify a collection of objects to JSON, and then read them in your iPhone app. I'm assuming you're asking for how to convert from object-to-JSON, and that you've already covered JSON-to-object. I'll cover object-to-JSON here.
What you'll need to do is create a class that contains all of the information you need in your JSON file, like so.
public class Location
{
public string Place { get; set; }
public string Hotel { get; set; }
public string Telephone { get; set; }
}
Now, inside your database reader statement, you'll want to construct a List<Location>, and then add each Location to this list. Once you've done this, you'll easily be able to convert the collection to JSON using the JSON.NET framework... which makes converting objects to JSON as easy as:
// "locations" is the name of the collection
JsonConvert.SerializeObject(locations);
JSON .NET Documentation
Hope this helps. :)

web service: getting the http parameter

Complete newbie in VS and C#, I am trying to setup a web service, starting by something very simple. I managed to write a class that will (hopefully) return an item's name, given the item's code. Now I want to implement this so that it can be called from the web, but I do not know how to retrieve the parameter. The idea is to have http://myurl.com?ProdRef=XYZ, and return the name of product XYZ.
Please don't shoot, this is my first try with C# and VS !
Edit: working code (for whom it may help)
Class code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
/// <summary>
/// Summary description for Class1
/// </summary>
class Product
{
public string ProdRef {get; set; }
public string ProdName{get; set; }
public static string GetLabel(string ProdRef)
{
//
// create a new SqlConnection object with the appropriate connection string
SqlConnection sqlConn = new SqlConnection("Data Source=ssss;Initial Catalog=ccccc;Persist Security Info=True;User ID=uuu;Password=pppp;Network Library=dbmssocn");
// open the connection
sqlConn.Open();
// create the command object
SqlCommand sqlComm = new SqlCommand("select libelle from dbo.vwArticlesPerm WHERE Ref = '" + ProdRef + "'", sqlConn);
string strResult = (string)sqlComm.ExecuteScalar();
// close the connection
sqlConn.Close();
return strResult;
}
}
Web service code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
/// <summary>
/// Summary description for WebService
/// </summary>
[WebService(Namespace = "http://xxxxx.lu/clientwebserv")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {
public WebService () {
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
public string GetName(string prName) {
return Product.GetLabel(prName);
}
}
I think you should define GetName in this way
[WebMethod]
public string GetName(string name)
{
return Product.GetLLabel(name);
}
When a client app loads your WSDL, xml returned shows that GetName function wants a string in input and gives back a string. That's all.
Next: don't build queries manually joining strings, int, dates, use Parameters.
SqlCommand sqlComm = new SqlCommand(
"select libelle from dbo.vwArticlesPerm WHERE Ref = #par", sqlConn);
cmd.Parameters.AddWithValue("#par", ProdRef);
If you want to use GetLabel, you must add public to its declaration or you won't be able to see it outside its class!
public static string GetLabel(string ProdRef)
{
string strResult = null;
using (SqlConnection sqlConn = new SqlConnection("server=xxx;uid=yyy;pwd=zzz;database=myerp;"))
{
sqlConn.Open();
using (SqlCommand sqlComm = new SqlCommand("select libelle from dbo.vwArticlesPerm WHERE Ref = '" + ProdRef + "'", sqlConn))
strResult = (string)sqlComm.ExecuteScalar();
sqlConn.Close();
return strResult;
}
}
Another advise I give you is to use using(...) when instantiating classes that implements IDisposable interface: when execution exits from using block classes are disposed, so you can avoid memory waste and some headache :)

Categories