I'm trying to submit data to a web service in my project. The data's in the form of several fields, so I'd rather create a single object and submit that. I know I can submit it as a JSON object, but I thought I'd seen code somewhere that would create a C# object on the JS side so that I could submit it to the web service.
Am I crazy, or what does this JS code look like?
Just to get everyone on the same page example-wise, let's say the C# class would look like this:
namespace NSTest
{
[Serializable]
public class ClassTest
{
public string ClassName;
public int ClassValue;
}
}
And the web service would look like this:
namespace NSTest
{
public class WebServiceTest
{
[WebMethod]
public void WSFunc(ClassTest test)
{
...
}
}
}
Javascript variable would look like this:
var preparedParameters = {
ClassName: "Some name",
ClassValue: 10
};
But it depends how do you intend to call your web service, because you may have to wrap this variable inside some other object/array etc.?
Just for the better ease of client compatibility, have you maybe considered WCF web services because they are more configurable and provide bare format that doesn't need any wrapping etc.?
This should work for you
var test = {
ClassName:"classname",
ClassValue:1
};
Related
I have imported a third-party WSDL (via Service Reference) into my Console Application project in order to send and receive data through Web Services. In order to get this to function appropriately, I have had to add some code to the Reference.cs file associated to the Web Service. While this works, if an update is made to the WSDL, and I re-import/generate that Service Reference, that work-around code will go away.
In order to get around this, I have saved the necessary code-changes to an external text file saved within the project.
I'm curious if anyone knows of a way that I could write these changes into a their own separate class, outside of the Service Reference, and yet, still be referenced by the Service Reference, thus using the "correct" code needed to send/receive from the Web Service.
I have two classes (not included in the generated code) that I am able to reference in the generated code after separating them into their own .cs file and referencing the namespace used by the Service Reference.
What I would like to do, if possible, is the following:
Overall Goal:
Add custom code to code generated by importing a third-party WSDL as a Service Reference, that way when the WSDL is updated by the third-party, another developer would not have to necessarily remember to dive into the Reference.cs file of the Service Reference, and replace/add specific code.
To achieve this goal, I need to be able to:
Replace an existing property and associated field of the generated
partial class, with a customized version (see Snippet #1 below).
Replace an existing generated partial class with a customized version of the class, having a different attribute definition and slightly different property/field definitions.
Snippet #1
Replace the following:
private byte[] bulkExchangeFileField;
[System.Xml.Serialization.XmlElementAttribute(Namespace = "urn:us:gov:treasury:irs:common", DataType = "base64Binary", Order = 0)]
public byte[] BulkExchangeFile
{
get { return this.bulkExchangeFileField; }
set
{
this.bulkExchangeFileField = value;
this.RaisePropertyChanged("BulkExchangeFile");
}
}
with this version of the properties/fields that worked once I altered the generated code:
private BulkExchangeFileType bulkExchangeFileField;
[System.Xml.Serialization.XmlElementAttribute(Namespace = "urn:us:gov:treasury:irs:common", Order = 0)]
public BulkExchangeFileType BulkExchangeFile
{
get { return this.bulkExchangeFileField; }
set
{
this.bulkExchangeFileField = value;
this.RaisePropertyChanged("BulkExchangeFile");
}
}
Use extension methods and/or overload the properties in an inhered class, so your code will not be replaced.
To overload the properties you just need to declare it with the word new before public like in : new public BulkExchangeFileType BulkExchangeFile, so when you use the object it will call your properties instead the ones defined by the web service
and here is how to create extention methods https://msdn.microsoft.com/library/bb383977.aspx
class Program
{
static void Main(string[] args)
{
InheredClass test = new InheredClass(); // Do this
BaseClass test2 = new InheredClass(); // don't do this
Console.WriteLine(test.MyProperty.GetType());
Console.WriteLine(test2.MyProperty.GetType());
Console.Read();
}
class BaseClass
{
public int MyProperty { get; set; }
}
class InheredClass : BaseClass
{
new public decimal MyProperty { get; set; }
}
}
Version 1 of my ASP.NET Web API for Ember.js was producing JSON that looked like this:
[{"id":1,"name":"House of Crap","category":"Retail","street_name":"Washington Street"},
{"id":2,"name":"Sketchy Automotive","category":"Automotive","street_name":"4th Street"},
{"id":3,"name":"Toxins Are Us","category":"Chemical","street_name":"Highway 93"},
{"id":4,"name":"Tricky Restaurant","category":"Restaurant","street_name":"4th Street"}]
I need something that looks like this:
{"property":
[{"id":1,"name":"House of Crap","category":"Retail","street_name":"Washington Street"},
{"id":2,"name":"Sketchy Automotive","category":"Automotive","street_name":"4th Street"},
{"id":3,"name":"Toxins Are Us","category":"Chemical","street_name":"Highway 93"},
{"id":4,"name":"Tricky Restaurant","category":"Restaurant","street_name":"4th Street"}]}
One of my subs accomplished this as follows: He created a simple view-model class.
namespace EnvironWeb.ViewModels
{
public class PropertyVM
{
public IEnumerable<property> property { get; set; }
}
}
He then made the GetProperties controller method of the type of the new class.
public PropertyVM GetProperties()
{
var model = new PropertyVM();
model.property = repository.GetAll();
return model;
}
It's clever, but is it the best approach? The JsonConverter looks promising, but I'm not sure I can accomplish it with the JsonConverter.
This is not the best approach, this is the correct approach :)
Bur I would suggest to review your model. Why do you need root property in the answer? Does it have any business meaning? If only reason for this root property is some simplification of code on client side - may be it's better to keep API clean and just do the work on client side?
I am working on application that has WCF REST API and below some DAL. Everything is written in C#.
All REST methods are GET, but many of them have generic string parameter (among other params) that I parse and map to a list object. It works well.
When it comes to mapping to Dto object I would like to use some design pattern to instantiate correct Dto based on mapped REST params. Not sure is it possible since I have that generic string parameter (param name will not be the same all the time) ?
Also, based on created Dto type I would like to choose appropriate DB method to call, command design pattern for this one, I guess?
Thanks for help,
I could explain more if needed.
I have developed same kind of application (WCF REST service).
I have created .net solution and added below project
BusinessLayer
DataAcessLayer
DataService (WCF Service)
EntityLayer
DataService:
public SnapshotData GetSnapshot(string symbol, int nocache)
{
SnapshotData objSnapshotData;
try
{
objSnapshotData = (new SnapshotBAL()).GetSanpshotData(symbol);
SerializeObject(objSnapshotData, localCacheKey);
return objSnapshotData;
}
catch (Exception ex)
{
return null;
}
}
BusinessLayer:
namespace BusinessLayer
{
public class SnapshotBAL
{
public Snapshot GetSanpshot(string symbol)
{
return (new SnaapshotDAL()).GetSanpshot(symbol);
}
}
}
EntiryLayer:
namespace EntityLayer
{
public class Snapshot
{
public DateTime time { get; set; }
public double price { get; set; }
}
}
DataAccessLayer:
namespace DataAccessLayer
{
public class SnaapshotDAL : PrototypeDB
{
public Snapshot GetSanpshot(string symbol)
{
AddParameter("o_snapshot");
AddParameter("i_symbol", symbol);
Snapshot objSanapshot = new Snapshot();
return ObjectHelper.FillObject<Snapshot>(typeof(Snapshot), GetReader("A_SM7_V1_P.GetSnapshotQuick"));
}
}
}
The key line in the question is this:
...design pattern to instantiate correct Dto based on mapped REST params
To me this sounds like you want to use the Factory Pattern.
Urgh. Yes I know, cargo cult programming etc, BUT(!), there are good reasons:
You want to intialise a class (the DAL) based upon some settings
You want those settings defined at the top level (REST mapping)
You want lower level code to be totally ignorant of the settings (right?) so that they can change arbitrarily without requiring system wide refactors.
Sure, you could always just pass an instance of the DAL down the stack but that isn't always possible and can get a bit scrappy.
Alternatively...
Consider creating a DAL implementation that can be made aware of the various switches and will delegate calls to the correct DAL implementation. This might actually be lighter weight than a straight up factory.
Apparently my education has failed me, because I didn't realize that methods in C# cannot be serialized. (Good to know.)
I am trying to create a WCF service that returns a simple class I created. The problem is that this simple class contains methods that I want to expose, and the caller of my service won't have any access to them (assuming they won't have a .dll containing the class declaration).
public class Simple
{
public string Message { get; set; }
private const string _Hidden = "Underpants";
public string Hidden
{
get { return _Hidden; }
}
public string GetHidden()
{
return _Hidden;
}
}
I set up a WCF service (let's call it MyService) to return an instance of my Simple class. To my frustration, I'm only getting a partial build of my class back.
public void CallService()
{
using (var client = new MyService.Serviceclient())
{
Simple result = client.GetSimple();
string message = result.Message; // this works.
string hidden = result.Hidden; // this doesn't.
string fail = result.GetHidden(); // Underpants remains elusive.
}
}
Is there any type of workaround where I'm able to set up a property or method on my class that will be accessible to whomever calls my service? How does one handle constants or other methods that are set up in a class that only exists in a service?
Typically you would create three different projects.
1. Service project
2. Client project
3. Data project
The Data project contains only the data classes - no application code. The methods and constants in these data classes should be independent of the Service/Client projects.
The Data project is included as a reference in both the Service and Client projects so that serialization and deserialization happen against the same binary - and you get to retain your constants/methods/etc.
The downside here is that all your clients will either have to be .NET apps, or you will have to provide different data libraries for each platform you wish to support.
As far as I know the only things that can be returned in a WCF service are primitives or a class with public properties that have a get method on them. From a high level WCF exists to allow you to specify a contract between the client and the server that it in theory transportation agnostic (ie you can swap out an HTTP endpoint for a netTcp endpoint and the service will function the same way from a contractual level).
The question to answer then is what data are you trying to pass back in this service call. If it's an object called simple with the data points of Message and Hidden then I would advise creating a data class called Simple that has those values as properties:
[DataContract]
public class Simple
{
[DataMember]
public string Hidden { get; set; }
[DataMember]
public string Message { get; set; }
}
When the client receives the response back Message and Hidden will be populated with whatever you have set their values to on the server side.
The DataMember attribute can only be used on properties and fields. This means that a WCF response can only serialize these types.
If you really want to only use the const in your WCF contract You could convert it to a field and place the DataMember attribute on it:
public class Simple
{
[DataMember]
public string Message { get; set; }
[DataMember]
public const string Hidden = "Underpants";
}
To be able to do this the field must be accessible (public).
Add the DataMember attribute to your property. To do so, you must have both a get and a set defined.
[DataMember]
public string Hidden
{
get { return _Hidden; }
set { }
}
technically you could do
public class thingToSerialize{
public Func<ArgType1,ArgType2...,ReturnType> myFunction{get;set;}
}
and then assign it a lambda that takes the arguments and returns the return type
before serializing
Can I send an object from client-side javascript to server-side code via ASP.NET?
In ASP.NET WebForms i would use a ScriptService:
Checkout this samples: http://msdn.microsoft.com/en-us/magazine/cc163499.aspx
The GenerateScriptType attribute can used if you wanna pass/get hole objects to the service:
ASP.NET ScriptService deserialization problem with derived types
[WebService(Namespace = "http://msdnmagazine.com/ws")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[GenerateScriptType(typeof(Object1))]
[GenerateScriptType(typeof(Object2))]
[ScriptService]
public class StockQuoteService : WebService
{
static Random _rand = new Random(Environment.TickCount);
[WebMethod]
public int GetStockQuote(string symbol)
{
return _rand.Next(0, 120);
}
}
Yes. One way could be, to use a web method; for instance:
Create a service
Call from the JavaScript method like: DataService.Push(yourObject);
For instance:
Javascript methods:
function btnGenerate_onclick(result) {
DataService.Push(getDataFromSomeDiv(), onGenerateReportComplete /*callback method*/);
//or
//DataService.Push(document.getElementById("myDiv").innerHTML, onGenerateReportComplete /*callback method*/);
}
function onGenerateReportComplete(result) {
alert("Success:" + result);
}
Service methods:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class DataService : System.Web.Services.WebService
{
[WebMethod(EnableSession = true)] //If you want?
public bool Push(object someObject)
{
//var v = someObject as MyObjectClass;//Process object
return true;
}
}
EDIT: How would javascript know what is server-side DataService?
This will require reference of web service in the markup. For instance like following:
<asp:ScriptManager ID="sm" runat="server">
<Services>
<asp:ServiceReference Path="DataService.asmx" />
</Services>
</asp:ScriptManager>
Or you can use callbacks/page methods.
Not as such. You can serialise the object to a string, send that string to ASP.NET and then convert it into an object again on the other side.
JSON is a good serialization format for this, and you can drop simple objects directly into the various libraries that are around for it (and that are listed in the penultimate section of the JSON homepage).
For more complex objects, you will need to extract the relavent bits of data you need to recreate them before doing that.
Ben Dotnet is right about using a ScriptService in asp.net WebForms. In addition to using the ScriptService decorator the GenerateScriptType decorator is important in order to make sure that the complex type you're wanting to use is included. I found the articles Ben linked to be useful in addition to this one: http://www.webreference.com/programming/asp-net-ajax/complex-data-types/index.html
Here is how I was able to do exactly what you're trying. First I defined the custom type I wanted to use in my code behind file.
namespace TestProject
{
public class SampleData
{
public int id { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public SampleData()
{ }
}
public partial class SamplePage : System.Web.UI.Page
{
/* The rest of the SamplePage.aspx.cs file goes here */
}
}
Then I created a WebMethod/ScriptMethod in my SamplePage code behind like this:
[WebMethod]
[ScriptMethod]
[GenerateScriptType(typeof(SampleData))]
public static bool EditReminder(SampleData data)
{
/* Server side code goes here */
return true;
}
Then, on the client-side page I was able to create an object of type SampleData and pass that using the PageMethods like this. Don't forget to include the namespace, this is necessary.
function some_javascript_function () {
var sample_data = new TestProject.SampleData()
sample_data.id = 1;
sample_data.StartDate = '6/24/1976';
sample_data.EndDate = '3/20/2012';
PageMethods.EditReminder(sample_data, OnEditReminderComplete)
}
function OnEditReminderComplete () {
if (result) alert("Success!");
else alert("Failure!");
}
Also, don't forget to include the script manager and enable page methods like this somewhere on your page:
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" />
Yes. You can use Json and do POST. If you are using jQuery you can use $.ajax to post the values to server side. Hope this helps.