C#.NET WebService returning object - c#

I am creating a Web Service using ASP.NET C#. I am sending various data types from the webservice so I use the following structure.
public enum WS_ServiceResponseResult
{
Success,
Failure,
}
public class WS_ServiceResponse
{
public WS_ServiceResponseResult result { get; set; }
public object data { get; set; }
}
public class WS_User
{
public long id{ get; set; }
public string name{ get; set; }
}
Webservice Sample Method
[WebMethod(EnableSession = true)]
public WS_ServiceResponse LogIn(string username, string pasword)
{
WS_ServiceResponse osr = new WS_ServiceResponse();
long userID = UserController.checkLogin(username, pasword);
if (userID != 0)
{
osr.result = WS_ServiceResponseResult.Success;
osr.data = new WS_User() { id = userID, name = username };
}
else
{
osr.result = WS_ServiceResponseResult.Failure;
osr.data = "Invalid username/password!";
}
return osr;
}
I am using two client types, javascript and C#.NET Windows Form. When I call from javascript I get no problem and the osr.data is filled with WS_User. So i can use osr.data.id easily. But when I use from C#.NET (proxy is generated using "Add Web Reference") I can successfully call but when the result arrives I get a Soap Exception
{System.Web.Services.Protocols.SoapException:
System.Web.Services.Protocols.SoapException:
Server was unable to process request.
---> System.InvalidOperationException: There was an error generating the XML
document. ... ...
What am I missing? I Guess object is not well defined and causing the problems. What are the workarounds?
Thanks
Maksud
Addition:
If add the following dummy method, then it works nicely. Hope it helps, to get the solution.
[WebMethod]
public WS_User Dummy()
{
return new WS_User();
}

I had a similar Problem returning an "object" (multiple classes possible)
Here is a sample code:
[Serializable()]
[XmlRoot(ElementName="Object")]
public sealed class XMLObject
{
private Object _Object;
[XmlElement(Type=typeof(App.Projekte.Projekt), ElementName="Projekt")]
[XmlElement(Type=typeof(App.Projekte.Task), ElementName="Task")]
[XmlElement(Type=typeof(App.Projekte.Mitarbeiter), ElementName="Mitarbeiter")]
public Object Object
{
get
{
return _Object;
}
set
{
_Object = value;
}
}
}
I think you should change your code this way:
[XmlRoot(ElementName="ServiceResponse")]
public class WS_ServiceResponse
{
public WS_ServiceResponseResult result { get; set; }
[XmlElement(Type=typeof(WS_User), ElementName="WS_User")]
[XmlElement(Type=typeof(string), ElementName="Text")]
public object data { get; set; }
}

Related

.NET Core API REST C# List into List is null

I'm developing an api in net core.
I've done a post function in which I send an object containing multiple parameters and a list within another list.
When I'm debugging the code the function is called correctly but I find that the second list always arrives null.
The rest of the data arrives at you correctly. I have done different tests with other objects and everything works correctly.
It is this case in which the list within another the second one arrives null.
My code:
example request input
{
"Name": "TestName",
"Related1":
[{
"id1": "TestNameRelated1",
"Related2":
[{
"id2": "TestNameRelated2"
}]
}]
}
[HttpPost]
public resultExample Test([FromBody]TestClass test)
{
//do something
}
[DataContract]
public class TestClass
{
[DataMember]
public string Name { get; set; }
[DataMember]
public List<TestClassArray> Related1 { get; set; }
}
[DataContract]
public class TestClassArray
{
[DataMember]
public string id1 { get; set; }
[DataMember]
public List<TestClassArray2> Related2 { get; set; }
}
[DataContract]
public class TestClassArray2
{
[DataMember]
public string id2 { get; set; }
}
This api was previously made in .NET framework 4.8 and this case worked correctly.
Now I'm passing the api to .Net5.
Could it be that in .Net5 it is not allowed to pass lists within other lists?
Do you have to enable some kind of configuration to be able to do this now?
You need use class/DTO with constructor like shown below and you should be good to go. I have uploaded this sample API app's code working with .net5.0 on my GitHub here.
public class TestClass
{
public TestClass()
{
Related1 = new List<TestClassArray>();
}
public string Name { get; set; }
public List<TestClassArray> Related1 { get; set; }
}
public class TestClassArray
{
public TestClassArray()
{
Related2 = new List<TestClassArray2>();
}
public string id1 { get; set; }
public List<TestClassArray2> Related2 { get; set; }
}
public class TestClassArray2
{
public string id2 { get; set; }
}
public class ResultExample
{
public string StatusCode { get; set; }
public string Message { get; set; }
}
Controller Post Method
[HttpPost]
[ProducesResponseType(typeof(ResultExample), 200)]
public ResultExample Post([FromBody] TestClass test)
{
ResultExample testResult = new ResultExample();
TestClass test2 = new TestClass();
TestClassArray testClassArray = new TestClassArray();
TestClassArray2 testClassArray2 = new TestClassArray2();
test2.Name = test.Name;
foreach (var item in test.Related1)
{
foreach (var item2 in item.Related2)
{
testClassArray2.id2 = item2.id2;
}
testClassArray.Related2.Add(testClassArray2);
}
test2.Related1.Add(testClassArray);
Console.WriteLine(test2);
testResult.Message = "New Result added successfullly....";
testResult.StatusCode = "201";
return testResult;
}
Swagger Input Sample Payload
Post Controller Result
Response of Sample input payload,(You can change it to default 201 response code as well)
I had a similar issue.
API method shows List was null
In my case a date field was not well formatted
So I use SimpleDateFormat on Android Studio with a correct datetime format
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss",Locale.US);
item.setDate(dateFormat.format(calendar.getTime()));
and works fine

C# Web api getting POST data from JSON

I have an issue that I've been trying to solve. I'm trying to send data from a java application to a web server, but I can't figure out how to actually send it. The java code is as follows:
String hStr = "{\"id\":2,\"name\":\"John\",\"height\":36.72342538,\"width\":2.99999998,\"frequency\":871.07,\\"idList\":[],\"level\":0.0}";
House ap = toJsonMap.readValue(hStr, House.class);
when: "ask the server to add a house from the request"
def response = server.httpClient.requestSpec { spec ->
spec.body { b ->
b.text(hStr)
b.type("application/json")
}
}
.post("//modeling/housing/{hid}/prop/point/in");
I then have the C# read this code like this:
[Route("modeling/housing/{hid}/prop/point/in")]
[HttpPost]
public HttpResponseMessage AddPoint(int hid, int id, string name, double height, double width, double frequency, List<int> idList, double level)
{
DAL.House h = new DAL.House();
try
{
using (DAL.Entities context = DAL.Entities.CreateContextForComplex(said))
{
if (!context.Houses.Where(a => a.Id == id).Any())
{
h.Name = name;
h.Height = height;
h.Width = width;
h.Frequency = frequency;
h.IdList= idList;
h.Level = level;
h.LastModified = System.DateTime.UtcNow;
context.Houses.Add(ap);
context.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK, ap);
}
else
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, "Housing id already exists");
}
}
}
catch (EntityException)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, "Entity Exception");
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
}
}
I just can't figure out how to get the data from this post. Particularly getting all of the different types of variables. I found a lot of different answers, but nothing seems to work.
Most likely you need to create a class that has properties matching the incoming request post body's object properties. For example:
public class House
{
public int Hid { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public double Height { get; set; }
public double Width { get; set; }
public double Frequency { get; set; }
public List<int> IdList { get; set; }
public double Level { get; set; }
}
Then you would update your method signature as follows:
public HttpResponseMessage AddPoint(House house)
Try to create a class that represents all the properties in the JSON Object:
public class YouClass
{
public int Id { get; set; }
public string Name { get; set; }
public string Height { get; set; }
......
// add others
}
Then in your controller:
public class HousingController : ApiController
{
[Route("AddPoint")
[HttpPost]
public HttpResponseMessage AddPoint([FromBody] YourClass)
{
}
}
Then modify the URL of API your are calling:
.post("api/Housing/Addpoint")
Your URL might be different, you might use : http://localhost:Port/api/Housing/Addpoint and the port. Make sure you try it in browser first or use Postman. Check this
.post("//modeling/housing/{hid}/prop/point/in");
This line of code should give you a timeout in your java, if this is exactly how you have it typed. What you really want here is something more like:
.post("http://localhost:PortNumber/modeling/housing/"+ ap.id +"/prop/point/in");
Where PortNumber is the port your web api is running on, and ap.Id is the Id of the record you are trying to modify.
After you have corrected your endpoint situation, then move on to the other answers and use JSON.Net to deserialize your JSON back into a class.

ServiceStack How generate an Json response with only the Primary Key?

When I create a new record in my table I would like generate an json response with only the primary ID of my new record, somethink like : {"PrimaryID":123}
I actually use this handmade function:
// Inserts a new row into the PatientSession table
public string AddPatientSession(PatientSession p)
{
int id = (int)_dbConnection.Insert<PatientSession>(p, selectIdentity: true);
string Idconvert = id.ToString();
string IdInsert = "{\"PatientSessionId\":" + Idconvert + "}";
return IdInsert;
}
But I assume it's not the best way to do it, have you a suggestion please?
Thanks in advance
If you just want to return a small JSON payload with just an Id you can use a type with only the fields you want to return, e.g:
public class AddPatientSession : IReturn<PatientId> { ... }
public class PatientId {
public int PatientSessionId { get; set; }
}
Then use in your service like:
public class MyServices : Service
{
public object Any(AddPatientSession request)
{
var model = request.ConvertTo<PatientSession>();
return new PatientId {
PatientSessionId = Db.Insert(model, selectIdentity: true);
}
}
}
Returning an object takes advantage of ServiceStack's built-in Content Negotiation to return the object serialized in the preferred Content-Type, e.g. JSON for JSON/ajax clients.
You can also return an anonymous type containing just the Id:
public object Any(AddPatientSession request)
{
var model = request.ConvertTo<PatientSession>();
return new {
PatientSessionId = Db.Insert(model, selectIdentity: true);
}
}
Which will also serialize to JSON when requested, but the lack of a type does prevent this from being called with ServiceStack's generic typed Service Clients.
Thanks you so much #mythz it's working well I just use a convert function to int because "Db.Insert" return a long type.
// Add PatientSession via POST
public class PatientSessionADD : IReturn<PatientSessionResponseId>
{
public int PatientSessionId { get; set; }
public int ByPatientId { get; set; }
public DateTime PatientStartSessionTime { get; set; }
public int PatientStartSessionByUserId { get; set; }
public DateTime PatientEndSessionTime { get; set; }
public int PatientEndSessionByUserId { get; set; }
}
public class PatientSessionResponseId
{
public int PatientSessionId { get; set; }
}
public object Post(PatientSessionADD request)
{
var p =new PatientSession()
{
ByPatientId = request.ByPatientId,
PatientStartSessionTime = request.PatientStartSessionTime,
PatientStartSessionByUserId = request.PatientStartSessionByUserId
};
return new PatientSessionResponseId
{
PatientSessionID = Convert.ToInt16( Db.Insert<PatientSession>(p, selectIdentity: true) )
};
}
To resume this function get a HTTP POST message, store it in database and return a JSON response with only the Primary ID generated.
Have fun and thanks again mythz

JSON Deserialize Error: Parameter cannot be null

Couldn't find an answer from the other Json Serialization issue questions, so maybe someone can help me:
I'm getting a JSON object from a REST api and attempting to Deserialize it to an object. Below is the JSON Object I receive:
{"id":"6wVcZ9ZF67ECUQ8xuIjFT2",
"userId":"83ca0ab5-3b7c-48fe-8019-000320081b00",
"authorizations":["employee","API","trainer","queueAdmin","supervisor","workflowAdmin","realtimeManager","forecastAnalyst","qualityEvaluator","contactCenterManager","teamLead","personnelAdmin","telephonyAdmin","qualityAdmin","businessAdmin","businessUser","accountAdmin","dialerAdmin","contentManagementUser","contentManagementAdmin","admin","api","scriptDesigner","agent","user"],
"primaryAuthorization":"employee",
"thirdPartyOrgName":"in",
"username":"somebody",
"selfUri":"https://blahblahblah.com/api/v1/auth/sessions/6wVcZ9ZF67ECUQ8xuIjFT2"}
And my object I'm attempting to DeSerialize to:
[Serializable]
public class Session : BaseRequest, ISession
{
public Session(string url) : base(url)
{
}
#region Members
[JsonProperty(PropertyName = "userId")]
public string UserId { get; set; }
[JsonProperty(PropertyName = "authorizations")]
public object[] Authorizations { get; set; }
[JsonProperty(PropertyName = "primaryAuthorization")]
public string PrimaryAuthorization { get; set; }
[JsonProperty(PropertyName = "thirdPartyOrgName")]
public string ThirdPartyOrgName { get; set; }
[JsonProperty(PropertyName = "username")]
public string Username { get; set; }
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "selfUri")]
public string SelfUri { get; set; }
#endregion
}
I simply make the web request and get the response stream using a stream reader and return the string. Pretty standard.
However, when I attempt to Deserialize into my Session object it always throws an error: Value Cannot be Null
var serializer = new JsonSerializer();
response = MakePostRequest(true);
var obj = serializer.Deserialize<Session>(new JsonTextReader(new StringReader(response)));
The response is the JSON string I get back from the web request and is exact to what I specified above.
I've done this before but normally I've been the one that designed the REST api. Not the case this time but I can't for the life of my figure out why this won't deserialize? I've specified the JSonProperty PropertyName to avoid issues with proper casing, is this not working right maybe? Any help is appreciated!
UDPATE
I think I found part of the problem. It is attempting to deserialize my base class which consists of :
public abstract class BaseRequest
{
protected BaseRequest(string apiUrl)
{
ApiUrl = apiUrl;
Request = (HttpWebRequest)WebRequest.Create(apiUrl);
}
public string ApiUrl { get; set; }
public string JsonPayload { get; set; }
public HttpWebRequest Request { get; private set; }
}
Is there any directive I can give to prevent it from doing so? Or will I need to refactor around this?
Below code works (using Json.Net):
var session = JsonConvert.DeserializeObject<Session>(json);
public class Session
{
public string Id { get; set; }
public string UserId { get; set; }
public List<string> Authorizations { get; set; }
public string PrimaryAuthorization { get; set; }
public string ThirdPartyOrgName { get; set; }
public string Username { get; set; }
public string SelfUri { get; set; }
}
EDIT
How should I tell it to ignore the base class?
var session = (Session)System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(typeof(Session));
JsonConvert.PopulateObject(DATA, session);
But I don't think this is a nice way of doing it. Changing your design may be a better solution.
I've tested your code and it works fine, only change I made was removing the constructor, I take it that the serializer can't create an instance on the object for some reason, can you remove
public Session(string url) : base(url)
{
}
Your code works just fine for me but I haven't the BaseRequest source code so I made class with empty constructor.
IMO the exception is coming exactly from there. In the Session constructor the url parameter is null because your JSON object doesn't have url property. May be in the BaseRequest class you use this url param and you receive the Value Can't be Null error.
You can change just the name of parameter if this is the issue:
public Session(string selfUri ) : base(selfUri)
{
}
Check also if the 'response' variable is null. StringReader can throw this exception if you pass null to its constructor.

error when calling the webservice

i am getting a list of pagepack assistant by calling a webservice. I have added the web reference.
using org.xerox.xde3.na.sdi.amiller_v_vista;
public org.xerox.xde3.na.sdi.amiller_v_vista.DDCControl proxy;
in page load method i am calling the web method as follows
proxy = new DDCControl();
Guid y = new Guid("45a5b1c2-2fa5-4136-abdd-bc213b694848");
DataList1.DataSource = proxy.GetAllDDCs(this.AccountID, y);
DataList1.DataBind();
I am getting the following error:
An invalid data source is being used for DataList1. A valid data source must implement either IListSource or IEnumerable
public DDCReturnGetAll GetAllDDCs(Guid accountId, Guid authToken);
the return type of GetAllDDCs is DDCReturnGetAll
where
public class DDCReturnGetAll : DDCReturnBase
{ public DDCReturnGetAll();
public DDCInfo2[] DDCs { get; set; } }
where
DDCInfo2 is
public class DDCInfo2 { public DDCInfo2();
public BrandingType brandingType { get; set; }
public string ChargebackName { get; set; }
public string CollectorName { get; set; }
public string Description { get; set; }
public string URL { get; set; } }
Can you please help me with this issue?
The object returned from GetAllDDCs doesn't implement IListSource or IEnumerable. Most likely the object returned has a property on it that you should bind to instead.
You will need to look at the return type from the procy.GetAllDDCs method and see what it is returning.
The error message you are getting shows that the DataList1 control cannot find a way to enumerate the items for binding.

Categories

Resources