How can i read SOAP body as one parameter in C# - c#

This is a sample request to a web service I'm working on:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns0:postRequest xmlns:ns0="http://www.mynamespace.com">
<Firstname>Mike</Firstname>
<Lastname>Adam</Lastname>
</ns0:postRequest>
</S:Body>
</S:Envelope>
Currently I read each value as single parameter in the webmethod like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
namespace myCode
{
[WebService(Namespace = "http://www.mynamespace.com")]
public class testInt : System.Web.Services.WebService
{
[SoapRpcMethod("http://www.mynamespace.com")]
[WebMethod]
public string postRequest(string Firstname, string Lastname)
{
return Lastname.ToString();
}
}
}
But in the real case there are much more parameters.
My question is how can read them as one parameter in the webmethod noting that I can't change the request XML format.
(By the way I created a class with Firstname and Lastname as properties in it and used this class as a parameter in the webmethod but it's always null)
Thanks much

I think this is what you are after. It shows you how to make an XML model binder. https://lostechies.com/jimmybogard/2011/06/24/model-binding-xml-in-asp-net-mvc-3/
EDIT:
Something a little more pointed I just found is http://docs.asp.net/en/latest/mvc/models/model-binding.html which talks about a Microsoft.AspNet.Mvc.Formatters.Xml nuget package. That is probably your best bet.

Related

Azure Functions: Cannot apply attribute class 'Queue<T>' because it is generic

I'm using Visual Studio Code to develop an Azure Durable Function, following some online examples. I'm completely new to Azure and adapting to C# from VB.NET. I already developed a working durable function that stores data in a blob table. This is a slight adaptation of that which aims to put the information into a queue.
I'm following the instructions here, and have code that I think should work, except that it tells me this:
Cannot apply attribute class 'Queue<T>' because it is generic
However I've looked at some other examples, including the one from Microsoft, and don't anything special being done for typing of queue. Clearly, though, I'm missing something.
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Mvc;
namespace Test.Groove
{
public static class GrooveWebhook
{
[FunctionName("GrooveWebhook")]
public static async Task<List<string>> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var outputs = new List<string>();
GrooveItem data = context.GetInput<GrooveItem>();
string res = await context.CallActivityAsync<string>("AddToQueue", data);
return outputs;
}
[FunctionName("AddToQueue")]
public static async Task<String> Run(
[ActivityTrigger] GrooveItem trans,
[Queue("incoming-groove-webhooks")] IAsyncCollector<GrooveItem> GrooveData,
ILogger log)
{
await GrooveData.AddAsync (trans);
return $"Added Groove transaction for {trans.firstname} {trans.lastname}: {trans.email}";
}
[FunctionName("GrooveWebhook_HttpStart")]
public static async Task<HttpResponseMessage> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
{
// Function input comes from the request content.
var data = await req.Content.ReadAsAsync<GrooveItem>();
string instanceId = await starter.StartNewAsync("GrooveWebhook", data);
log.LogInformation($"Started Groove webhook orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
}
}
Now, here's the really weird part. I followed along literally step by step with their http trigger example, code as follows, and yet don't have that same error:
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace My.Functions
{
public static class HttpExample
{
[FunctionName("HttpExample")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
[Queue("outqueue"),StorageAccount("AzureWebJobsStorage")] ICollector<string> msg,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
string responseMessage = string.IsNullOrEmpty(name)
? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
: $"Hello, {name}. This HTTP triggered function executed successfully.";
return new OkObjectResult(responseMessage);
}
}
}
So then, as if that wasn't weird enough, I went back to my original project that added data to a table, and just added this little queue binding statement, and I don't have the error! This is so crazy. Code begins:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Mvc;
namespace Company.Function
{
public static class GrooveOrchestrationTest
{
[FunctionName("GrooveOrchestrationTest")]
public static async Task<List<string>> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context,
[Table ("GrooveData")] IAsyncCollector<GrooveItem> GrooveData,
[Queue ("GrooveQueue")] IAsyncCollector<GrooveItem> GrooveQueue)
There are no additional using directives in either of the latter solutions that successfully bind the queue for output.
One Additional Thought
I created another version from scratch with the exact same problem, even though my other one is still fine. I have no explanation for this. However, I will note that they are connected to DIFFERENT Azure accounts. Both are on the free tier, both just signed up in the last couple of days. I can't fathom why that should matter, but it's all I can think of.
This problem is caused by the following reference added automatically by VS Code into the .csproj file:
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" />
This is confirmed by changing it to match the reference from the other solution where the exact same code works perfectly:
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.3" />
With this change in reference, it works as expected.
What lead me to this is the fact that my queue binding worked fine when pasted into my older solution from just a few days ago, but the exact same code didn't work in the new solution. To ensure all things were equal, I pasted the entire contents of the .cs file so there would be no difference. I.e. the old solution and the new one had identical .cs files, but one worked and one didn't.
Since my code was identical in both solutions, it seemed clear that there must be something that VS Code had done behind the scenes. I did a stare-and-compare on all its automatically generated files between the old solution and the new one. I discovered that this one reference is literally the only difference between the two solutions, and when I change it to the older version, things work beautifully.
I'll reference the older package for now so I can get this done, and then when I get some free time figure out how to make the new SDK.Functions happy.
You might be lacking reference to Microsoft.Azure.WebJobs.Extensions.Storage.

List Vs Datatable in web api response

I'm new in web api and I wrote a code in which I return a datatable in an IHttpActionResult and I want to know what is the difference between return a datatable and a list or dictionary.
this is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebApplication2.BLL;
namespace WebApplication2.Controllers
{
public class HomeController : ApiController
{
public IHttpActionResult getpro()
{
var tabla= new Conexion().table();
tabla.TableName = "tablilla";
return Ok(tabla);
}
}
}
I am testing this in post man and is runing well, but I want to know if should I sent a list in the response or another object.
There might not be an apparent difference right now, but as your application grows, you might run into maintainability issues.
The issue is that right now, the signature of your API endpoint (i.e. what data it returns) is hard coupled to your database, so if you change your database, so does the result returned by your endpoint. That's usually a bad thing for anything but the smallest/simplest applications, since it might break consumers of your API.
What you'd do instead, is create models specifically for returning from your API endpoints and then convert (also called map) your datatable to a list of these "view"-models. This way, you can change the backend of your web API without it (immediately) having an impact on your frontend (or other consumers of your API).

REST post method difficulty

There is an application which is used for taking surveys. I want to use REST api and add some questions to the survey. So basically I want to update some pages of the survey. Here are the links of that application.
My surveys name is trial and the page number that I want to update is 2.
fields#updateobject
Here is my code to do. But i think the http call I have used is not correct. and I am not able to figure out how to make the request.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
namespace ConsoleApplication1
{
class Program
{
private static object post;
private static object response;
static void Main(string[] args)
{
RunAsync().Wait();
}
static async Task RunAsync()
{
string webReq = "https://restapi.survey.com/v4/survey/trial/surveypage/2?_method=POST?api_token="/*token goes here*/;
// $.post{webReq};
}
}
}
Use System.Net.Http.HttpClient class for sending requests to any API. Tutorial and examples on sending various requests (GET, POST, etc.) can be found here.

Can't access web service methods, but can access the MethodNameCompletedEventArgs and MethodNameCompletedEventHandler

This is my first time dealing with making my own web service, and I made a basic one, which I am currently only needing to access locally:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Xml;
namespace WebService1
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
#region Temp Conversion
[WebMethod]
public string F2C(int f)
{
double c = 5.0 / 9.0 * (f - 32);
return c.ToString();
}
}
}
This works when I run this and run the method through the browser. However I've added it to another project, a windows form application, via "Add Service Reference" < Advanced
But now within the project when I try to access the methods they don't show.
I do:
MyWebService.
I named the referenced service "MyWebService", and all thats available is:
F2CCompletedEventHandler
F2CCompletedEventArgs
Service1
as opposed to
MyWebService.F2C
On its own being available right away.
you need to create an Instance of the myWebService object can you show the code where you are consuming / creating the proxy and or instance..? sounds like you need to use fully qualified name in regards to the namespace + the class name
Example:
MyWebService.Service1 myService = new MyWebService.Service1();
to call the method do the following
myService.F2C(15); // for example

WCF Service- Does not implement interface member

I am following a guide on how to add authorization in a WCF service located here.
Now my problem is when I create the service and remove the .DoWork() method from it, I get an error that says:
'Testing.HelloService' does not implement interface member 'Testing.IHelloService.DoWork()
This is obviously because I removed it, but is it needed? In the guide it basically said to remove the .DoWork() method from it, so I am geussing the person who wrote it missed something.
When I create it service it adds the HelloService and IHelloService files to the project. Do I need to add changes to IHelloService?
Here is the code in HelloService.svc.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Web;
using System.ServiceModel.Activation;
namespace MLA_Test_Service
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "HelloService" in code, svc and config file together.
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class HelloService : IHelloService
{
public string HelloWorld()
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
return HttpContext.Current.User.Identity.Name;
else
return "Unauthenticated Person";
}
}
}
Here is the code from IHelloService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace MLA_Test_Service
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IHelloService" in both code and config file together.
[ServiceContract]
public interface IHelloService
{
[OperationContract]
void DoWork();
}
}
Your implementation needs to match your interface. If you don't want to implement the DoWork method, it needs to go from the implementation and the Interface.
In fact, you probably should just replace DoWork with the name of the method you actually want to invoke on the service and implement that method instead. It's supposed to serve as an example of how to initiate an operation on the WCF service.
its simple C#, you are inheriting an interface, you must implement all the declared methods of it in the class.
DoWork() exists in your Interface, hence implement it in your HelloService class.
Moreover, only those methods will be visible to your WCF-Service client, which will be declared in OperationContract i.e. the Interface and is marked [OperationContract]

Categories