Receiving the error "Object reference not set to an instance of an object" when posting JSON data to the below WCF Service.
My guess is the employee object isn't initialised but I'm unsure where that should be done as when I used a string a test it worked just fine.
Any suggestions are greatly appreciated.
Interface (IAccount.cs):
[ServiceContract(Namespace = "AccountService")]
public interface IAccountService
{
[OperationContract, WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string CreateAccount(Employee employee);
}
[DataContract]
public class Employee
{
[DataMember]
public string firstName { get; set; }
[DataMember]
public string lastName {get; set;}
}
Implementation (AccountService.svc)
AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class AccountService: IAccountService
{
public string CreateAccount(Employee employee)
{
string test = employee.firstName;
return test;
}
}
JSON Post Data:
{"firstName":"Test","lastName":"User"}
OK finally sorted this out, hopefully this helps someone with the same issue.
My initial JSON looked correct but doesn't work:{"firstName":"Test","lastName":"User"}. But by looking at the server trace you can see the inbuilt XML DeSerializer cannot map the elements to the object in the WCF Service method (employee object in my case) and this is the cause of the null reference error.
Putting the form attributes inside an object that matches the name of the service parameter however did the trick: {"employee":{"firstName":"test"}}
By default, WebGet's RequestFormat is set to XML. Set it to Json.
Related
I have a WCF to save some data to my db. In Dev Tools I can see the request payload as below:
{"OrderId":123456,"Year":"2017","CustomerId":999999,"LicencePlates":[{"licenceNumber":"222222222222222"}]}
My WCF service interface is as below:
[OperationContract]
[WebInvoke(UriTemplate = "/SaveLicenceData", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
void SaveLicenceData(int OrderId, int Year, string CustomerId, LicencePlate[] LicencePlates);
The licence plate class is:
public class LicencePlate
{
[DataMember]
public string LicenceNumber { get; set; }
}
With a breakpoint set, I can see the OrderId getting passed, the Year getting passed and the CustomerId getting passed. However LicenceNumber I keep getting null passed.
I tried making the overall class [Serializable] but the breakpoint isn't even getting hit when I add this. I also tried changing the annotation too [DataMember(Name = "licenceNumber")] but still getting null and then changed the annotation to [JsonProperty] and still getting null.
Is there something stupid I have missed here?
I think you have a case mismatch. In your payload you have
"licenceNumber":"222222222222222"
It should be
"LicenceNumber":"222222222222222"
I have the following output from a C# web service:
{"CallResult":[{"CompanyId":"AAA900134-904","CompanyName":"MID"}]}
I want the output to only contain an array of JSON like the following:
[{"CompanyId":"AAA900134-904","CompanyName":"MID"}]
I'm not sure how to customize the output. Do I have to return a string and customize the JSON manually or is there another way? Thanks.
Without more information, such as actual data example (this json refers to 1 object only), here is what I can suggest:
Create 2 custom classes as follows:
public class CallResultClass
{
public List<InnerClass> CallResult { get; set; }
}
public class InnerClass
{
public string CompanyId { get; set; }
public string CompanyName { get; set; }
}
Then, along with using System.Web.Script.Serialization;, you can deserialize the json as follows:
string json = "{\"CallResult\":[{\"CompanyId\":\"AAA900134-904\",\"CompanyName\":\"MID\"}]}";
JavaScriptSerializer js = new JavaScriptSerializer();
var callres = (CallResultClass)js.Deserialize(json, typeof(CallResultClass));
var companyInfo = callres.CallResult;
If your json contains a list of CallResults, a simple modification to the code can accommodate for that. There is no scenario where modifying the json string would be viable (there is always a clean way).
For reference & examples read JavaScriptSerializer Class.
I figured out a solution.
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/CallResult/{username}/{company}")]
CallResult_Result[] CallResult(string username, string company);
I had to change
BodyStyle = WebMessageBodyStyle.Wrapped
to
BodyStyle = WebMessageBodyStyle.Bare
I'm just starting out in C# and am a little stuck on this.
I need to return a custom error message when a user doesn't have access to a particular resource.
Interface class for service:
[ServiceContract]
public interface IPatientDemographics
{
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "GetPatientDemographics/{strHospId}/{strView=mobile}",
ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
[return: MessageParameter(Name = "PatientDemographicsResultSet")]
List<PatientDemographics> GetPatientDemographics(string strHospId, string strView);
[OperationContract]
[FaultContract(typeof(AccessError))]
[return: MessageParameter(Name = "Error")]
AccessError ReturnAccessError();
}
[DataContract]
public class AccessError
{
[DataMember]
public bool Error { get; set; }
[DataMember]
public string Message { get; set; }
}
Service class:
[ServiceBehavior(AddressFilterMode=AddressFilterMode.Any)]
public class PatientDemographics : IPatientDemographics
{
public List<PatientDemographics> GetPatientDemographics(string strHospId, string strView)
{
AuthenticationDAO authenticationDAO = new AuthenticationDAO();
string userName = GetUserNameFromHeader();
if (authenticationDAO.CheckPatientSealAccess(strHospId, userName, "-1", "N"))
{
PatientDAO patientDAO = new PatientDAO();
patientDAO.AuditPatient(strHospId, userName);
return patientDAO.GetPatientDemographics(strHospId);
}
else
{
AccessError serviceData = new AccessError();
serviceData.Error = true;
serviceData.Message = "User does not have access to patient record";
throw new FaultException<AccessError>(serviceData, "User does not have access to patient record");
}
}
}
At the moment, this just returns a null object if the user doesn't have access. I tried throwing a FaultException but had no luck. Ideally I want it to return in JSON format something like:
{
error: "User does not have access to patient record"
}
You have to use Channel Dispatcher to add error handler and define custom fault contract.
There is good article about Error handling in WCF 3.5. It is long way to describe what you need as I was penalised for posting URL. I would suggest you to look in code project for
"WCF Error Handling and Fault Conversion". A good article written by Sasha Goldshtein.
Hope this helps.
Trying to construct valid request to wcf restful service. But whole hour cannot do it, i dont get it why it's not work. Other APis what returns JSON works correctly, i tested them. Now need to fix request API.
I put break point to implementation of AddMeal method but she don't triggered. I think something wrong with my request or with Attributes
//Add Meal
[OperationContract]
[WebInvoke(UriTemplate = "AddMeal",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, Method = "POST")]
bool AddMeal(string meal);
Your WCF method is expecting a string, however, the model binder will try to bind your JSON to a string which won't work. When using MVC you should use models instead, create a model that represents your JSON data e.g.
public class Meal
{
public DateTime EatedTime { get; set; }
public decimal Amount { get; set; }
public int PatientID { get; set; }
public int MealTypeID { get; set; }
...
}
Then update your signature to expect that model
bool AddMeal(Meal meal)
You should find the data is bound to the meal model.
I am creating a wcf self hosted service. I am using UriTemplate class to customize the urls to methods. the code snippet is given below
public interface ISelfService
{
[WebInvoke(Method = "POST", UriTemplate = "ack/{errorcode}/{uniquefileid}")]
[OperationContract]
void Ack(ErrorCode errorcode, string uniquefileid);
[WebInvoke(Method = "POST", UriTemplate = "filechanged/{metainfo}")]
[OperationContract]
void FileChanged(MetaInformation metainfo);
}
Whenever i run this program i am getting the following error
Operation 'FileChanged' in contract 'ISelfHostService' has a query
variable named 'metainfo' of type 'Natash.Common.MetaInformation',
but type 'Natash.Common.MetaInformation' is not convertible by
'QueryStringConverter'. Variables for UriTemplate query values must
have types that can be converted by 'QueryStringConverter'
Can any one tell me why is this happening?
And, I have not made any modification to the web.config file. Do i need to make any modification there?
MetaInformation is defined as follows
[DataContract]
public struct MetaInformation
{
[DataMember]
public string Author { get; set; }
[DataMember]
public string tags { get; set; }
[DataMember]
public string categories { get; set; }
[DataMember]
public string description { get; set; }
}
try this
public interface ISelfService{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/ack?errorcode={errorcode}&uniquefileid={uniquefileid}")]
void Ack(ErrorCode errorcode, string uniquefileid);
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/filechanged")]
void FileChanged(MetaInformation metainfo);}
From the message you posted it sounds like there are 2 definitions for the MetaInformation class (Gettrix.Common.MetaInformation & Natash.Common.MetaInformation).
It could be that both are in scope for WCF to see when instantiating the service. If so, it might think that the one that does not have a DataContract attribute (probably Natash.Common.MetaInformation) is what you are reffering to and therefore would not be usable for data transfer within the service.