Want to call a web service with .aspx extension. It cannot add to web references.Then I used webclient and return string. But then I do not Know how to use it. This is my code.
WebClient client = new WebClient();
detail.Title = client.DownloadString("https://somename/cruiseproducts.ashx");
return downloadedString;
It depends on what is returned by you service
for example
you ashx service should look like this
public class TestHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("Hello World");
}
public bool IsReusable
{
get
{
return false;
}
}
}
on your side client code should look like this
WebClient client = new WebClient();
var testResult = client.DownloadString("http://localhost:19238/TestHandler.ashx");
return testResult;
Noitice that service is returning "plain/text" type
if service is returning xml type then u can simply get string firstly and then parse like this
//consider that result is in testResult variable
var xml = new XmlDocument();
//your xml tree
xml.LoadXml(testResult);
Related
i am trying to send encrypted request to asp.net web api and want web api to intercept the request and decrypt or modify it before it gets bind to controller action method.
Any help will be appreciate.
What you could do is write your custom filter. Since you want to decode the body content before it gets bind, you will have to use AuthorizeAttribute.
public class DecryptRequestContent : System.Web.Http.AuthorizeAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
var requestContent = actionContext.Request.Content;
var newContent = Decryption (requestContent);
actionContext.Request.Content = newContent;
}
}
After that, you will have to decorate your API with this filter like this:
public class SomeController : ApiController
{
[DecryptRequestContent]
public void SomeMethod(DataModel model)
{
// implementation goes here
}
}
I think the solution is
actionContext.Request.Content = new StringContent(newContent,Encoding.UTF8,"application/json");
Hopefully it can help!
Updated for .net core, authorization attribute that changes the body of the request
public class Authorize0ActionFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var requestContent = new StringContent("new body", Encoding.UTF8, "application/json");
var stream = requestContent.ReadAsStream();//modified stream
context.HttpContext.Request.Body = stream;
}
}
public class Authorize0Attribute : TypeFilterAttribute
{
public Authorize0Attribute()
: base(typeof(Authorize0ActionFilter))
{
//Arguments = new object[] { permission };
}
}
I am trying to consume/call an MVC Web API controller method, which will be used to upload a file. I am struggling to call it from my MVC controller.
Here's my code for the API Controller
public class ImportController : ApiController
{
[HttpPost]
public bool PutImportFile(byte[] fileToBeImported, string nameOfTheFileToBeImported)
{
// I am doing file saving stuff here
}
}
I have tested the file saving part by changing the method to HttpGet and its working when I called it directly from the browser. I removed the parameters for that.
However, I am not able to figure out how to call it from a client.
I have tried below.
public class ImportFileModel
{
public byte[] FileToBeImported { get; set; }
public string NameOfTheFileToBeImported { get; set; }
}
The below code will accept a file from the browser uploaded by user and post it to the API controller to save the file.
[HttpPost]
public async Task<JsonResult> Upload()
{
byte[] file;
string fileName = string.Empty;
if (Request.Files.Count > 0)
{
try
{
fileName = Request.Files[0].FileName;
using (MemoryStream ms = new MemoryStream())
{
Request.Files[0].InputStream.CopyTo(ms);
file = ms.ToArray();
}
//To do: get url from configuration
string url = "http://localhost:(port)/api/Import/PutImportFile";
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/bson"));
ImportFileModel request = new ImportFileModel
{
FileToBeImported = file,
NameOfTheFileToBeImported = fileName
};
MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter();
var result = await client.PostAsync(url, request, bsonFormatter);
HttpResponseMessage response = result.EnsureSuccessStatusCode();
}
}
catch (Exception ex)
{
// exception handling here
}
}
return Json(true, JsonRequestBehavior.AllowGet);
}
It ends up in an exception at the last line.
HttpResponseMessage response = result.EnsureSuccessStatusCode();
Throwing 404 not found error.
I have also tried the same from a console application using HttpWebRequest. It also throws the same error.
Your Web API method PutImportFile is setup to receive two values, not a single model; hence, your HttpClient call is not recognized (no matching route found). Change your Web API method to receive a model:
public class ImportController : ApiController
{
[HttpPost]
public bool PutImportFile(ImportFileModel fileInfo)
{
//Your code to save the file...
}
}
I'm trying to create a proxy WCF service over a WCF service using ChannelFactory.
I have defined the following interface for the WCF service to call. It has a generic GetResource method that writes directly into HttpContext the response byte[] and sets it's content type based on the type of the resource.
[ServiceContract]
public interface ITest
{
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "getResource/?resourceKey={resourceKey}")]
void GetResource(string resourceKey);
}
Proxy implementation for GetResource:
public void GetResource(string resourceKey)
{
var factory = new ChannelFactory<ITest>(GetCustomBinding(), new EndpointAddress('https://test.com/mytest.svc'));
channel.Endpoint.Behaviors.Add(new WebHttpBehavior());
var channel = factory.CreateChannel();
using (var scope = new OperationContextScope((IContextChannel)channel))
{
channel.GetResource(resourceKey);
}
}
private static Binding GetCustomBinding()
{
var binding = new WebHttpBinding(WebHttpSecurityMode.Transport)
{
MaxReceivedMessageSize = 20000000,
MaxBufferSize = 20000000,
MaxBufferPoolSize = 20000000,
CloseTimeout = TimeSpan.FromMinutes(1)
};
binding.ContentTypeMapper = new JsonMapper();
return binding;
}
private class JsonMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Json;
}
}
The problem that I have is that when I'm calling the proxy at this endpoint, proxy.svc/GetResource?resourceKey="text.css" it returns the right content type but no actual content, ContentLength=0.
How should I handle Response Body forwarding? How do I read the response body? I tried using WebOperationContext.Current.IncomingResponse but it doesn't give me the response body as well.
I think you are attempting to use WCF in a way that it is not intended. A void method will return nothing. In theory, you can intercept this by adding an inspection behaviour, but not even sure that would work.
I have (potentially) similar code which loads file from a database and returns them, but that will return the content.
var file = ServiceUtilities.FileManager.GetFile(id);
if (file != null)
{
var fcr = new FileContentResult(file.Content, file.MimeType);
return fcr;
}
Perhaps you should revisit your intended approach.
When adding WebService Reference to an ASMX Service on a .NET 2.0 project for example,
var objService = new NameSpace.groupservices();
there exists,
objService.CookieContainer = new System.Net.CookieContainer();
When adding ServiceReference to an ASMX Service on a .NET 4.0 project for example,
var objService = new NameSpace.groupservicesSoapClient();
there isn't any CookieContainer property for objService
A similar question was asked here with no positive solution.
Could someone please guide where to find the property?
In contrast to ASMX Web Services that are tied to HTTP transport, WCF allows for various transport protocols to be used. Therefore, not all protocol-specific options (such as Cookies for HTTP transport) are available in a WCF service reference.
You can, however, add a message inspector that inspects the messages that are sent between client and server. This article describes a way to send cookies to the server.
I've extended the sample to use a CookieContainer. Also, the following code shows how to evaluate the Set-Cookie header sent by the server to add the new cookies to the container. Please note that the sample shows a basic outline, but might need extension or some more validation. However, in a simple scenario it worked.
The following snippet shows a test method of a WCF service that is hosted on IIS and integrated in the ASP.NET framework. It basically echoes the cookies sent to the server in a string and adds two new ones:
public string GetData(int value)
{
var reply = string.Join(", ",
from x in HttpContext.Current.Request.Cookies.AllKeys
select x + "=" + HttpContext.Current.Request.Cookies[x].Value);
HttpContext.Current.Response.Cookies.Add(new HttpCookie("Test", "Test123"));
HttpContext.Current.Response.Cookies.Add(new HttpCookie("Test2", "Test1234"));
return reply;
}
The following test program creates a CookieContainer for the cookies, adds a demo cookie and registers a new behavior for the endpoint of the service:
class Program
{
static void Main(string[] args)
{
var cookieCont = new CookieContainer();
using(var svc = new TestServiceReference.TestServiceClient())
{
cookieCont.Add(svc.Endpoint.Address.Uri, new Cookie("TestClientCookie", "Cookie Value 123"));
var behave = new CookieBehavior(cookieCont);
svc.Endpoint.EndpointBehaviors.Add(behave);
var data = svc.GetData(123);
Console.WriteLine(data);
Console.WriteLine("---");
foreach (Cookie x in cookieCont.GetCookies(svc.Endpoint.Address.Uri))
Console.WriteLine(x.Name + "=" + x.Value);
}
Console.ReadLine();
}
}
The behavior serves the purpose of adding a custom message inspector and handing over the CookieContainer:
public class CookieBehavior : IEndpointBehavior
{
private CookieContainer cookieCont;
public CookieBehavior(CookieContainer cookieCont)
{
this.cookieCont = cookieCont;
}
public void AddBindingParameters(ServiceEndpoint serviceEndpoint,
System.ServiceModel.Channels
.BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint,
System.ServiceModel.Dispatcher.ClientRuntime behavior)
{
behavior.MessageInspectors.Add(new CookieMessageInspector(cookieCont));
}
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint,
System.ServiceModel.Dispatcher
.EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint serviceEndpoint) { }
}
The message inspector both adds cookies when a request is sent to the server in the BeforeSendRequest method and retrieves the cookies that should be updated in the AfterReceiveReply method. Note that the correlationState returned by BeforeSendRequest is used to retrieve the Uri in the AfterReceiveReply:
public class CookieMessageInspector : IClientMessageInspector
{
private CookieContainer cookieCont;
public CookieMessageInspector(CookieContainer cookieCont)
{
this.cookieCont = cookieCont;
}
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply,
object correlationState)
{
object obj;
if (reply.Properties.TryGetValue(HttpResponseMessageProperty.Name, out obj))
{
HttpResponseMessageProperty httpResponseMsg = obj as HttpResponseMessageProperty;
if (!string.IsNullOrEmpty(httpResponseMsg.Headers["Set-Cookie"]))
{
cookieCont.SetCookies((Uri)correlationState, httpResponseMsg.Headers["Set-Cookie"]);
}
}
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,
System.ServiceModel.IClientChannel channel)
{
object obj;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out obj))
{
HttpRequestMessageProperty httpRequestMsg = obj as HttpRequestMessageProperty;
SetRequestCookies(channel, httpRequestMsg);
}
else
{
var httpRequestMsg = new HttpRequestMessageProperty();
SetRequestCookies(channel, httpRequestMsg);
request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMsg);
}
return channel.RemoteAddress.Uri;
}
private void SetRequestCookies(System.ServiceModel.IClientChannel channel, HttpRequestMessageProperty httpRequestMessage)
{
httpRequestMessage.Headers["Cookie"] = cookieCont.GetCookieHeader(channel.RemoteAddress.Uri);
}
}
Open your app.config file and add allowCookies="true" to the binding.
Something like this:
<binding allowCookies="true" />
Found the solution in here:
http://msdn.microsoft.com/en-us/library/bb628649.aspx
It turns out I need a web reference instead of a service reference
How can one call SOAP webservices from ASP.NET code in runtime and not by adding them as a reference/web-reference in compile time.
This is assuming that the application is aware of the list of web services url, the methods and parameters required to call each of the URLs.
Thanks in advance
Vijay
Supposing that you want to invoke the following method:
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
[WebMethod]
public string HelloWorld(Foo foo)
{
return "Hello World";
}
You need to construct the correct SOAP envelope:
using (WebClient client = new WebClient())
{
client.Headers.Add("SOAPAction", "\"http://tempuri.org/HelloWorld\"");
client.Headers.Add("Content-Type", "text/xml; charset=utf-8");
var payload = #"<?xml version=""1.0"" encoding=""utf-8""?><soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema""><soap:Body><HelloWorld xmlns=""http://tempuri.org/""><foo><Id>1</Id><Name>Bar</Name></foo></HelloWorld></soap:Body></soap:Envelope>";
var data = Encoding.UTF8.GetBytes(payload);
var result = client.UploadData("http://example.com/Service1.asmx", data);
Console.WriteLine(Encoding.Default.GetString(result));
}
And parse the resulting XML.