Web reference created dynamically - c#

I'm developing android app on Xamarin Android in c#.
Is there any way to change dynamically URL of SOAP web service? I want to store url in some kind of config file but I have no idea how do it.

correct me, if i'm wrong
but the second constructor of an xamarin - soap webservice class has a property for URL.
Here's an example of my webservice:
public partial class Service : System.Web.Services.Protocols.SoapHttpClientProtocol
{
public Service()
{
this.Url = "http://xxx/service.asmx";
}
public Service(string url)
{
this.Url = url;
}
}
you've added the webreference in xamarin and then use your webservice - instance.
Just call the second constructor and give them an other url as source.

You could manually create your required connection using Channelfactory that changes as it needs to. You'll need the proper connections in the web.config file.
Here's a way you could set it up.
In your web.config.
<appSettings>
<add key="Identity" value="machineidentity" />
<add key="Binding" value="WSHttpBinding_IService" />
<add key="Endpoint" value="http://Devservice/Service.svc" />
<add key="Identity2" value="localmachine" />
<add key="Binding2" value="WSHttpBinding_IService" />
<add key="Endpoint2" value="http://Devservice/Service.svc" />
<add key="devIdentity" value="localmachine" />
<add key="devBinding" value="WSHttpBinding_IService" />
<add key="devEndpoint" value="http://Devservice/Service.svc" />
</appSettings>
C# code
a configuration class to hold values from the web.config
public static Dictionary<int, Connections> EndpointConnections = new Dictionary<int, Connections>
{
{1, new Connections(){Identity = ConfigurationManager.AppSettings["Identity"],Binding = ConfigurationManager.AppSettings["Binding"], Endpoint = ConfigurationManager.AppSettings["Endpoint"]}},
{2, new Connections(){Identity = ConfigurationManager.AppSettings["Identity2"],Binding = ConfigurationManager.AppSettings["Binding2"], Endpoint = ConfigurationManager.AppSettings["Endpoint2"]}},
{3, new Connections(){Identity = ConfigurationManager.AppSettings["devIdentity"],Binding = ConfigurationManager.AppSettings["devBinding"], Endpoint = ConfigurationManager.AppSettings["devEndpoint"]}},
};
Now a static class for creating the endpoint
private ChannelFactory<IService> SetChannelFactory(int configInput)
{
var identity = EndpointIdentity.CreateDnsIdentity(Configuration.EndpointConnections[configInput].Identity);
var myBinding = new WSHttpBinding(Configuration.EndpointConnections[configInput].Binding);
var myuri = new Uri(Configuration.EndpointConnections[configInput].Endpoint);
var myEndpoint = new EndpointAddress(myuri, identity);
return new ChannelFactory<IService>(myBinding, myEndpoint);
}
Now calling and using the endpoint
public async Task<Result> SomeAction(int selection)
{
IService client = null;
Result result = null;
Response response = null;
using (var myChannelFactory = SetChannelFactory(selection))
{
try
{
client = myChannelFactory.CreateChannel();
response = await client.TheServiceFunction().ConfigureAwait(false);
((ICommunicationObject)client).Close();
}
catch
{
if (client != null)
{
((ICommunicationObject)client).Abort();
return new result ( failure = true);
}
}
}
if (response != null)
{
//Whatever you want to do with the response here
return new result ( failure = false);
}
}

Related

Trying to get file response from ASP.NET Web API

I have migrated some methods from a MVC controller to a Web API controller and now I have this method:
[HttpPost]
[Route("api/Request/UploadImage")]
public IHttpActionResult UploadImage()
{
try
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var httpRequest = System.Web.HttpContext.Current.Request;
if (_inMemoryStore == null)
{
_inMemoryStore = new List<FileLocalStore>();
}
if (httpRequest.Files.Count > 0)
{
var postedFile = httpRequest.Files[0];
var uniqueFileName = Guid.NewGuid().ToString();
var fileStream = new MemoryStream();
postedFile.InputStream.CopyTo(fileStream);
_inMemoryStore.Add(new FileLocalStore() { Id = uniqueFileName, File = fileStream });
var fileStore = new ServiceRequestAttachmentViewModel
{
FileName = httpRequest.Form["FileName"].ToString(),
FileMIME = httpRequest.Form["FileMIME"].ToString(),
UniqueFileName = uniqueFileName,
Thumbnail = fileStream.GetBuffer().GetThumbnailImage(80, 80),
IsPrivate = Convert.ToBoolean(httpRequest.Form["IsPrivate"].ToString()),
IsAdded = true,
IsDeleted = false
};
var content = JsonConvert.SerializeObject(fileStore);
// return Ok(fileStore);
return Content(HttpStatusCode.OK,fileStore);
}
else
{
return Ok(new { Data = "" });
//return Request.CreateResponse(HttpStatusCode.Created, new
//{ Data = "" });
}
}
catch (Exception ex)
{
Log.Error($"Error uploading image {ex.Message} {ex.InnerException} {ex.StackTrace}");
return BadRequest(ex.Message);
//var response2 = Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
//return response2;
}
}
In the original MVC controller, it was easy to return the ContentResult after fileStore was serialized. I want to do the same thing here but I'm having issues. It keeps saying it exceeds the maximum bytes but the file was only 10k big.
Is there something else I need to set? the media type received is a multipart/form-data type. The thumbnail property is the issue as it has bytes of data.
This is being called using fileupload() method of jQuery.
You probably net to update the maxRequestLength & maxAllowedContentLength in web.config
From MSDN, the maximum default size is 4MB
Here's the setting for 1GB
<system.web>
<httpRuntime maxRequestLength="2097152" requestLengthDiskThreshold="2097152" executionTimeout="240"/>
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>

BrowserStackLocal - could not connect to log files

I am trying to run automated selenium tests remotely using Browser stack local interacting with localhost. I get the following error:
Eror while executing BrowserStackLocal start {"state":"disconnected","pid":7512,"message":{"genre":"error","message":"Could not connect to Files!"}}
then I specify a log file, it then says:
BrowserStackLocal start {"state":"disconnected","pid":18308,"message":{"genre":"error","message":"Could not connect to -logFile!"}}
It hangs on this line with no further progress:
browserStackLocal.start(localArgs);
My code is as follows:
var capability = GetBrowserStackCapabilities();
SetBrowserStackLocal(capability);
webDriver = new RemoteWebDriver(new Uri("http://" + ConfigurationManager.AppSettings.Get("BrowserStackServer") + "/wd/hub/"), capability);
private static DesiredCapabilities GetBrowserStackCapabilities()
{
var profile = ConfigurationManager.AppSettings.Get("BrowserStackProfile");
NameValueCollection caps = ConfigurationManager.GetSection(string.Format("capabilities/{0}", profile)) as NameValueCollection;
var environment = ConfigurationManager.AppSettings.Get("BrowserStackEnvironment");
NameValueCollection settings = ConfigurationManager.GetSection(string.Format("environments/{0}", environment)) as NameValueCollection;
DesiredCapabilities capability = new DesiredCapabilities();
if (caps != null)
{
foreach (string key in caps.AllKeys)
{
capability.SetCapability(key, caps[key]);
}
}
if (settings != null)
{
foreach (string key in settings.AllKeys)
{
capability.SetCapability(key, settings[key]);
}
}
string username = Environment.GetEnvironmentVariable("BROWSERSTACK_USERNAME") ?? ConfigurationManager.AppSettings.Get("BrowserStackUser");
string accesskey = Environment.GetEnvironmentVariable("BROWSERSTACK_ACCESS_KEY") ?? ConfigurationManager.AppSettings.Get("BrowserStackKey");
capability.SetCapability("browserstack.user", username);
capability.SetCapability("browserstack.key", accesskey);
return capability;
}
private static void SetBrowserStackLocal(DesiredCapabilities capability)
{
if (capability.GetCapability("browserstack.local") != null && capability.GetCapability("browserstack.local").ToString() == "true")
{
var browserStackLocal = new Local();
string accesskey = Environment.GetEnvironmentVariable("BROWSERSTACK_ACCESS_KEY") ?? ConfigurationManager.AppSettings.Get("BrowserStackKey");
List<KeyValuePair<string, string>> localArgs = new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("key", accesskey),
new KeyValuePair<string, string>("logFile", "C:/Temp/logfile.txt"),
new KeyValuePair<string, string>("force", "true")
};
browserStackLocal.start(localArgs);
FeatureContext.Current.SetBrowserStackLocal(browserStackLocal);
}
}
My config is as follows:
<appSettings>
<add key="BrowserStackUser" value="<redacted>" />
<add key="BrowserStackKey" value="<redacted>/>
<add key="BrowserStackServer" value="hub-cloud.browserstack.com" />
<add key="BrowserStackProfile" value="single" />
<add key="BrowserStackEnvironment" value="ie11" />
</appSettings>
<capabilities>
<single>
<add key="browserstack.debug" value="true" />
<add key="browserstack.local" value="true" />
</single>
</capabilities>
<environments>
<ie11>
<add key="os" value="Windows" />
<add key="os_version" value="8.1" />
<add key="browser" value="IE" />
<add key="browser_version" value="11.0" />
<add key="resolution" value="1024x768" />
</ie11>
</environments>
How can I get past browser stack local hanging and start remote testing with a local server?
The error "Could not connect to -logFile!" is due to incorrect parameter "logFile". The correct parameter is "logfile" (all in lower case). You should check BrowserStack's documentation here - https://github.com/browserstack/browserstack-local-csharp#logfile.
Here is a working snippet for Browserstack local C# bindings:
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using BrowserStack;
using System.Collections.Generic;
using OpenQA.Selenium.Chrome;
using System.Threading;
namespace BrowserStackLocalSample
{
class Program
{
static void Main(string[] args)
{
IWebDriver driver;
var browserStackLocal = new Local();
List<KeyValuePair<string, string>> bsLocalArgs = new List<KeyValuePair<string, string>>() {
new KeyValuePair<string, string>("key", "<access_key>"),
new KeyValuePair<string, string>("logfile", "path_To_log/log.txt"),
//new KeyValuePair<string, string>("binarypath", "/Tools/local/BrowserStackLocal"),
new KeyValuePair<string, string>("force", "true"),
};
browserStackLocal.start(bsLocalArgs);
Thread.Sleep(15000);
DesiredCapabilities capability = new DesiredCapabilities();
capability.SetCapability("browser", "Chrome");
capability.SetCapability("browser_version", "62.0");
capability.SetCapability("os", "Windows");
capability.SetCapability("os_version", "7");
capability.SetCapability("resolution", "1024x768");
capability.SetCapability("browserstack.local", "true");
capability.SetCapability("browserstack.user", "<username>");
capability.SetCapability("browserstack.key", "<access_key>");
driver = new RemoteWebDriver(
new Uri("http://hub.browserstack.com/wd/hub/"), capability
);
driver.Navigate().GoToUrl("http://localhost:45691/check");
Console.WriteLine(driver.Title);
driver.Quit();
browserStackLocal.stop();
}
}
}

Where does authorization code go in C# PayPal REST API Winforms app?

I'm trying to access PayPal's API to submit invoices to clients through a C#.NET Winforms app, but I am terribly confused. Another user posted this code as a solution to connect:
public class PayPalClient
{
public async Task RequestPayPalToken()
{
// Discussion about SSL secure channel
// http://stackoverflow.com/questions/32994464/could-not-create-ssl-tls-secure-channel-despite-setting-servercertificatevalida
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
try
{
// ClientId of your Paypal app API
string APIClientId = "**_[your_API_Client_Id]_**";
// secret key of you Paypal app API
string APISecret = "**_[your_API_secret]_**";
using (var client = new System.Net.Http.HttpClient())
{
var byteArray = Encoding.UTF8.GetBytes(APIClientId + ":" + APISecret);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
var url = new Uri("https://api.sandbox.paypal.com/v1/oauth2/token", UriKind.Absolute);
client.DefaultRequestHeaders.IfModifiedSince = DateTime.UtcNow;
var requestParams = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "client_credentials")
};
var content = new FormUrlEncodedContent(requestParams);
var webresponse = await client.PostAsync(url, content);
var jsonString = await webresponse.Content.ReadAsStringAsync();
// response will deserialized using Jsonconver
var payPalTokenModel = JsonConvert.DeserializeObject<PayPalTokenModel>(jsonString);
}
}
catch (System.Exception ex)
{
//TODO: Log connection error
}
}
}
public class PayPalTokenModel
{
public string scope { get; set; }
public string nonce { get; set; }
public string access_token { get; set; }
public string token_type { get; set; }
public string app_id { get; set; }
public int expires_in { get; set; }
}
I'm afraid this is at least one step ahead of me as I can't figure out where in my project it is appropriate to paste the code. Let's just say you created a brand new C# Winforms app. Without getting into the specifics of creating an invoice, etc. What code would I need to support the PayPal API and where in the project does it go? I know I need to get authorization for the app from PayPal, but I'm having trouble finding a good "Getting Started" guide for C# and PayPal. I've created a REST API app on PayPal, so I do have a client ID and "secret" to pass for Oauth authorization - I just can't find a place to do that.
Thanks in advance. I have some C#.net programming experience, but honestly my programming experience mostly goes back to VB6 so I kind of need the big picture explanation. Thanks for your patience!!
Sorry for posting an answer here but I currently do not have enough reputation to post comment. However if you are still looking for a general idea on how to get this done then I can provide a brief example. Since you are using WinForms and PayPal's API, I am assuming you have setup your App.Config file already?
Example-
<!-- PayPal SDK settings -->
<paypal>
<settings>
<add name="mode" value="sandbox" />
<add name="clientId" value="insert_clientid_key_here" />
<add name="clientSecret" value="Insert_client_secret_key_here" />
</settings>
</paypal>
Once this has been addressed then you can make your way over to your form and input what you are going to use. Example:
using System;
using System.Windows.Forms;
using PayPal.Api;
using System.Collections.Generic;
Now that is completed you can create a button to make the API Call.
Example:
private void button1_Click_1(object sender, EventArgs e)
{
// Authenticate with PayPal
var config = ConfigManager.Instance.GetProperties();
var accessToken = new OAuthTokenCredential(config).GetAccessToken();
var apiContext = new APIContext(accessToken);
// Make an API call
var payment = Payment.Create(apiContext, new Payment
{
intent = "sale",
payer = new Payer
{
payment_method = "paypal"
},
transactions = new List<Transaction>
{
new Transaction
{
description = "Transaction description.",
invoice_number = "001",
amount = new Amount
{
currency = "USD",
total = "100.00",
details = new Details
{
tax = "15",
shipping = "10",
subtotal = "75"
}
},
item_list = new ItemList
{
items = new List<Item>
{
new Item
{
name = "Item Name",
currency = "USD",
price = "15",
quantity = "5",
sku = "sku"
}
}
}
}
},
redirect_urls = new RedirectUrls
{
return_url = "http://x.com/return",
cancel_url = "http://x.com/cancel"
}
});
MessageBox.Show("API Request Sent to Paypal");
}
Once completed, test it out and you should have a sandbox call waiting for you.

Silverlight not accessing content when using https

I have a SL app that has https and http endpoints. If i access the endpoint on http, then just have a screen which loads an external image
http://somedomain.com/domaimage.jpg
It will work fine.
If i access the SL app on https:// then load the same image it won't even attempt to make the web request for the image.
Why when SL is running on https i doesn't request external content? I have this in my clientaccesspolicy.xml
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*" http-methods="*">
<domain uri="http://*"/>
<domain uri="https://*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
and this is my crossdomain.xml
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>
Thanks
Steve
Now using an image proxy to access external content, if it helps anyone
ImageProxy.ashx
public class ImageUrlProxy : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
try
{
string url = context.Request.Headers["Url"];
var client = new WebClient();
byte[] imageDataBytes = client.DownloadData(url);
context.Response.ContentType = "application/json;";
context.Response.Write(JsonConvert.SerializeObject(imageDataBytes));
}
catch (Exception)
{
throw;
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
Helper class:
public static class ImageProxyHelper
{
public static void GetImageByProxy(string url, Action<BitmapImage> callback)
{
if (callback == null) return;
var client = new WebClient();
client.DownloadStringCompleted += (sender, args) =>
{
if (args.Error == null)
{
var buffer = JsonConvert.DeserializeObject<byte[]>(args.Result);
var im = new BitmapImage() { CreateOptions = BitmapCreateOptions.None };
im.SetSource(new MemoryStream(buffer));
callback(im);
}
};
client.Headers["Url"] = url;
client.DownloadStringAsync(UrlBuilder("ImageUrlProxy.ashx"));
}
public static Uri UrlBuilder(string fragment)
{
var uriBuilder = new UriBuilder(Application.Current.Host.Source.Scheme,
Application.Current.Host.Source.Host,
Application.Current.Host.Source.Port, fragment);
return uriBuilder.Uri;
}
}
Then from silverlight:
ImageProxyHelper.GetImageByProxy("http://externaldomain.com/image.jpg", p=>{
//Do something here
})
This can be extended to return any external content ^^
You are having the same problem as this question
Https and http Image URL Not loading in silverlight
It is down to cross scheme calls in silverlight

Onvif Event Subscription in C#

I am implementing an ipCamera/encoder management system in C#. The system will manage multiple ipCameras and/or encoders from a multiple vendors. Using Onvif instead off each ipcamera or encoders sdk will be a benefit.
One of the key concepts of the management system is to listen on events, such as motion detection events, from the cameras. Onvif supports this by use of the ws-basenotification or a pull type support. I don’t like pull, so I will use ws-basenotification support in Onvif (Onvif spec 9.1).
I have successfully added subscription to a Sony SNC-RH164, Bosh VIP X1 XF IVA and Acti TCD2100.
My problem is: I don’t get any notifications from any of the devices. Can anyone see what I'm doing wrong or give my som pointers on how to get notifications from devices.
My pc is on the same subnet as the devices. And my firewall is turned off for the test.
My test console app initiating the OnvifManager class.
using (var manager = new OnvifManager())
{
//manager.ScanForDevices();
var sonyDevice = new OnvifClassLib.OnvifDevice
{
OnvifDeviceServiceUri = new Uri(#"http://192.168.0.101/onvif/device_service"),
};
manager.AddDevice(sonyDevice);
manager.AddEventSubscription(sonyDevice, "PT1H");
var boshDevice = new OnvifClassLib.OnvifDevice
{
OnvifDeviceServiceUri = new Uri(#"http://192.168.0.102/onvif/device_service"),
};
manager.AddDevice(boshDevice);
manager.AddEventSubscription(boshDevice, string.Empty);
var actiDevice = new OnvifClassLib.OnvifDevice
{
OnvifDeviceServiceUri = new Uri(#"http://192.168.0.103/onvif/device_service"),
UserName = "uid",
Password = "pwd"
};
manager.AddDevice(actiDevice);
manager.AddEventSubscription(actiDevice);
Console.WriteLine("Waiting...");
Console.Read();
}
My managerClass will in the Constructor initialize my NotificationConsumer interface.
private void InitializeNotificationConsumerService()
{
_notificationConsumerService = new NotificationConsumerService();
_notificationConsumerService.NewNotification += NotificationConsumerService_OnNewNotification;
_notificationConsumerServiceHost = new ServiceHost(_notificationConsumerService);
_notificationConsumerServiceHost.Open();
}
My NotificationConsumer interface implementation.
/// <summary>
/// The client reciever service for WS-BaseNotification
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class NotificationConsumerService : NotificationConsumer
{
public event EventHandler<EventArgs<Notify1>> NewNotification;
/// <summary>
/// Notifies the specified request.
/// </summary>
/// <param name="request">The request.</param>
/// <remarks>A </remarks>
public void Notify(Notify1 request)
{
var threadSafeEventHandler = NewNotification;
if (threadSafeEventHandler != null)
threadSafeEventHandler.Invoke(this, new EventArgs<Notify1>(request));
}
}
public class EventArgs<T> : EventArgs
{
public EventArgs(T data)
{
Data = data;
}
public T Data { get; set; }
}
The config for NotificationConsumerService
<services>
<service name="OnvifClassLib.NotificationConsumerService">
<endpoint address="" binding="customBinding" bindingConfiguration="CustomBasicHttpBinding"
name="CustomHttpBinding" contract="EventService.NotificationConsumer" />
<host>
<baseAddresses>
<add baseAddress="http://192.168.0.10:8080/NotificationConsumerService" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<customBinding>
<binding name="CustomBasicHttpBinding">
<textMessageEncoding messageVersion="Soap12">
<readerQuotas maxStringContentLength="80000" />
</textMessageEncoding>
<httpTransport maxReceivedMessageSize="800000" maxBufferSize="800000" />
</binding>
</customBinding>
</bindings>
The AddDevice method
public void AddDevice(OnvifDevice device)
{
LoadCapabilities(device);
OnvifDevices.Add(device);
}
internal void LoadCapabilities(OnvifDevice onvifDevice)
{
if (onvifDevice.OnvifDeviceServiceUri == null)
return;
if (onvifDevice.DeviceClient == null)
LoadDeviceClient(onvifDevice);
try
{
onvifDevice.Capabilities = onvifDevice.DeviceClient.GetCapabilities(new[] { OnvifClassLib.DeviceManagement.CapabilityCategory.All });
}
catch (Exception ex)
{
Console.Write(ex.ToString());
}
}
private void LoadDeviceClient(OnvifDevice onvifDevice)
{
if (onvifDevice.OnvifDeviceServiceUri == null)
return;
var serviceAddress = new EndpointAddress(onvifDevice.OnvifDeviceServiceUri.ToString());
var binding = GetBindingFactory(onvifDevice);
onvifDevice.DeviceClient = new OnvifClassLib.DeviceManagement.DeviceClient(binding, serviceAddress);
if (!string.IsNullOrWhiteSpace(onvifDevice.UserName))
{
onvifDevice.DeviceClient.ClientCredentials.UserName.UserName = onvifDevice.UserName;
onvifDevice.DeviceClient.ClientCredentials.UserName.Password = onvifDevice.Password;
}
}
The AddEventSubscription method
public void AddEventSubscription(OnvifDevice onvifDevice, string initialTerminationTime = "PT2H")
{
if (onvifDevice.Capabilities.Events == null)
throw new ApplicationException("The streamer info does not support event");
try
{
if (onvifDevice.NotificationProducerClient == null)
LoadNotificationProducerClient(onvifDevice);
XmlElement[] filterXml = null;
var subScribe = new Subscribe()
{
ConsumerReference = new EndpointReferenceType
{
Address = new AttributedURIType { Value = _notificationConsumerServiceHost.BaseAddresses.First().ToString() },
}
};
if (!string.IsNullOrWhiteSpace(initialTerminationTime))
subScribe.InitialTerminationTime = initialTerminationTime;
onvifDevice.SubscribeResponse = onvifDevice.NotificationProducerClient.Subscribe(subScribe);
Console.WriteLine("Listening on event from {0}", onvifDevice.NotificationProducerClient.Endpoint.Address.Uri.ToString());
}
catch (FaultException ex)
{
Console.Write(ex.ToString());
}
catch (Exception ex)
{
Console.Write(ex.ToString());
}
}
private void LoadNotificationProducerClient(OnvifDevice onvifDevice)
{
var serviceAddress = new EndpointAddress(onvifDevice.Capabilities.Events.XAddr.ToString());
var binding = GetBindingFactory(onvifDevice);
onvifDevice.NotificationProducerClient = new OnvifClassLib.EventService.NotificationProducerClient(binding, serviceAddress);
if (!string.IsNullOrWhiteSpace(onvifDevice.UserName))
{
onvifDevice.NotificationProducerClient.ClientCredentials.UserName.UserName = onvifDevice.UserName;
onvifDevice.NotificationProducerClient.ClientCredentials.UserName.Password = onvifDevice.Password;
}
}
Bindings for Soap12
private Binding GetBindingFactory(OnvifDevice onvifDevice)
{
return GetCustomBinding(onvifDevice);
}
private Binding GetCustomBinding(OnvifDevice onvifDevice)
{
HttpTransportBindingElement transportElement = new HttpTransportBindingElement();
if (!string.IsNullOrWhiteSpace(onvifDevice.UserName))
transportElement.AuthenticationScheme = AuthenticationSchemes.Basic;
var messegeElement = new TextMessageEncodingBindingElement();
messegeElement.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None);
var binding = new CustomBinding(messegeElement, transportElement);
binding.SendTimeout = new TimeSpan(0, 10, 0);
return binding;
}
I had this problem with a GrandStream camera. I had to add one or more detection zones to it using the camera web UI to get it to detect motion.
I think the problem is, that your notification consumer uses AddressingVersion.None, while the notifications from the ONVIF device are formatted according to WS-Addressing 1.0. Try to change the following line of your GetCustomBinding method:
messegeElement.MessageVersion = MessageVersion.CreateVersion(
EnvelopeVersion.Soap12, AddressingVersion.None);
to
messegeElement.MessageVersion = MessageVersion.CreateVersion(
EnvelopeVersion.Soap12, AddressingVersion.WSAddressing10);

Categories