.Net 4.7 - Azure WebJob Project - JobHostConfiguration/RunAndBlock missing after NuGet updates - azure-webjobs

I had a working project with very dated NuGet package set for WebJob and storage. After a massive upgrade, I'm having three errors in this block only:
private static void Main()
{
var config = new JobHostConfiguration();
config.Queues.MaxDequeueCount = Convert.ToInt32(ConfigurationManager.AppSettings["MaxDequeueCount"]);
config.Queues.MaxPollingInterval = TimeSpan.FromSeconds(Convert.ToInt32(ConfigurationManager.AppSettings["MaxPollingInterval"]));
config.Queues.BatchSize = Convert.ToInt32(ConfigurationManager.AppSettings["BatchSize"]); ;
config.NameResolver = new QueueNameResolver();
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
var host = new JobHost();
host.RunAndBlock();
}
Errors:
Error CS0246: The type or namespace name 'JobHostConfiguration' could not be found (are you missing a using directive or an assembly reference?) \Program.cs:11
Error CS7036: There is no argument given that corresponds to the required formal parameter 'options' of 'JobHost.JobHost(IOptions<JobHostOptions>, IJobHostContextFactory)' \Program.cs:23
Error CS1061: 'JobHost' does not contain a definition for 'RunAndBlock' and no accessible extension method 'RunAndBlock' accepting a first argument of type 'JobHost' could be found (are you missing a using directive or an assembly reference?) \Program.cs:24
All the helps and questions are showing .Net Core code. I'm on .Net Framework 4.7.2. How do I go about setting up this code in old framework?

If you want to Azure WebJob SDK V3, the JobHostConfiguration and JobHost have been removed. In version V3, the host is an implementation of IHost. For more details, please refer to here and here. Besides, please note that in version 3, you need to explicitly install the Storage binding extension required by the WebJobs SDK.
For example (Queue trigger in version 3)
#Install package Microsoft.Azure.WebJobs.Extensions.Storage 3.x
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage(a => {
a.BatchSize = 8;
a.NewBatchThreshold = 4;
a.MaxDequeueCount = 4;
a.MaxPollingInterval = TimeSpan.FromSeconds(15);
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}

Related

Cannot find a handler of type EndpointResolver in AWSSDKS3

This is my issue:
I am updating AWS S3 nuget package from 3.7.1.2 to 3.7.101.25
Project details:
I have API that calls Class Library in which i am creating a AmazonS3Client. In version "3.7.1.2", its working fine. But in 3.7.101.25, i am getting below error.
Error:
System.InvalidOperationException HResult=0x80131509
Message=Cannot find a handler of type EndpointResolver
Source=AWSSDK.Core
Code:
var amazonS3Config = new AmazonS3Config()
{
MaxErrorRetry = maxRetryAttempts,
Timeout = TimeSpan.FromSeconds(requestTimeoutInSecond),
ServiceURL = serviceURL
}
s3Client = new AmazonS3Client(key, secret, amazonS3Config);
I was having the same issue where AWS looks like they opened up a ticket and resolved the issue. My issue was with AmazonKinesisClient but the same error.
https://github.com/aws/aws-xray-sdk-dotnet/issues/267 - same exception but for the AmazonDynamoDBClient.
This was resolved by installing the package AWSXRayRecorder.Handlers.AwsSdk v2.11.0

ASP.NET Core 3.1 upgrade issue

I am trying to upgrade my application to ASP.NET Core 3.1 and I am getting the below error when I am trying to Resolves a type using the type activator cache,
Below is the sample code,
The TypeActivatorCache isnt supported in ASP.NET Core 3.1 anymore and hence I have used the below code to replicate what it does in a nutshell, https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.Core/src/Infrastructure/TypeActivatorCache.cs
private TInstance CreateInstance<TInstance>(
IServiceProvider serviceProvider,
Type implementationType)
{
if (serviceProvider == null)
{
throw new ArgumentNullException(nameof(serviceProvider));
}
if (implementationType == null)
{
throw new ArgumentNullException(nameof(implementationType));
}
var createFactory = _typeActivatorCache.GetOrAdd(implementationType, _createFactory);
return (TInstance)createFactory(serviceProvider, arguments: null);
}
System.InvalidOperationException: 'Unable to resolve service for type 'Microsoft.AspNetCore.Hosting.IHostingEnvironment' while attempting to activate 'Microsoft.AspNetCore.Hosting.DefaultApplicationInsightsServiceConfigureOptions'.'
Any help would be much appreciated,

Webjob always publishes as Continuous and not Triggered

I have an Azure WebJob which I am publishing from visual studio 2017 to a Standard S1 App Service, the WebJob should be Triggered by CRON but always publishes as Continuous and I cannot figure out what I have done wrong (two other WebJobs publish fine)
I have the App Service set to 'Always On' in application settings
I have a settings.job file in the root with my schedule
{
"schedule": "0 3 5 * * 1-5"
}
My Program class
namespace EventPushUpdater
{
using Microsoft.Azure.WebJobs;
using MBL.AzureKeyVaultHelpers;
internal class Program
{
private static void Main()
{
Properties.Settings s = Properties.Settings.Default;
IKeyVault kv = new KeyVaultHelper(s.ClientId, s.ClientKey, s.KeyVaultRoot);
var config = new JobHostConfiguration();
config.DashboardConnectionString = kv.GetSecretValue(s.DashboardConnectionString);
config.StorageConnectionString = kv.GetSecretValue(s.DashboardConnectionString);
var host = new JobHost(config);
host.Call(typeof(Functions).GetMethod("PushEvents"), new { keyVault = kv });
}
}
}
And the function being called
public class Functions
{
[NoAutomaticTrigger]
public static void PushEvents(IKeyVault keyVault)
{
// do stuff
}
}
The first time you chose 'Publish as a WebJob', it asks you if you want Continuous or On Demand (which includes scheduled):
If you picked the wrong choice, simply delete webjob-publish-settings.json under Properties, and try again.
As an aside, your code is overly complex as you're needlessly using WebJobs SDK. Instead, your code can simply be:
static void Main()
{
// Do Stuff
}
You can switch between 'Continuous' and 'Triggered' modes by editing the webjob-publish-settings.json file that is found within the Properties folder of your WebJob project.
In this json file you can set "runMode:" to either Continuous or OnDemand (triggered) :
Continuous
OnDemand
Have you set { "is_singleton": true } in your settings.job?
If so you cannot run more than one instance of your WebJob. If you publish and run your WebJob to the Azure cloud you cannot never run it locally unless you use a different storage account.
Azure Webjob timer trigger does not fire

Use wsse security header in soap message (Visual Studio 2015, .Net Framework 4.5)

I would like to consume a Soap Service provided by DHL. You can find the wsdl here: https://wsbexpress.dhl.com/sndpt/expressRateBook?WSDL
Therefore I created a new ClassLibrary in Visual Studio 2015 targeting .net framework 4.5.
Then I added a Web Reference to the created project by providing the wsdl address. I generated a proxy file with all types and ports in it but my first problem is, that the generated Service extends from System.Web.Services.Protocols.SoapHttpClientProtocol. As I read in recent posts it is not possible to get the wsse header to that proxy. Some posts advise to add wse but it seems wse is not supported by newer Visual Studio versions.
I tried to generate my proxy by svcutil. After that I added the generated .cs file to the project and copied the content of the generated config file to app.config. (of cause I removed the web reference)
Now the Service class extends System.ServiceModel.ClientBase. (I thought the generator in VS uses svctool internally. If microsoft want people to use wcf why does the generator generate non-wcf proxy files.
I also created a nunit testproject which should test my service, but If I use the version with the svcutil generated version I get an error. I try to translate it to english as the error is displayed in german:
Could not find a default endpoint element which points to the service contract. As I figured out this is because the proxy is in its own class library and therefor doesn't really have an app.config. But my test project is a class library too.
What would be the actual way to consume a web service which needs ws security Username/Password auth these days?
You can add the Web Reference in compatibility mode (I am guessing you are doing so). If you are not adding the reference in compatibility mode, do the following:
Right click on references Add Service Reference-> Advanced -> Add Web Reference (Below the compatibility section), type the URL of the WS and add the reference.
The WSE2.0 extensions are available as a Nuget Package at:
https://www.nuget.org/packages/Microsoft.Web.Services2/
Install the nuget package on the package manager console running the following nugget command:
Install-Package Microsoft.Web.Services2
After you installed the nuget package, you need to make sure your project is referencing the following DLL's:
System.Web
System.Web.Services
Microsoft.Web.Services2 (This will be added after you install the nuget package)
In order to use the WSE2.0 extensions, you need to actually modify the Proxy class that was created when you added the WebReference to inherit from "Microsoft.Web.Services2.WebServicesClientProtocol" instead of "System.Web.Services.Protocols.SoapHttpClientProtocol". Be aware that if you update the WebReference, the Proxy class will inherit againfrom SoapHttpClientProtocol.
Add the following using clauses to the code consuming the Proxy class:
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
After you make this changes, you code should look something like this:
var token = new UsernameToken("theUser", "thePassword", PasswordOption.SendHashed);
var serviceProxy = new ExpressRateBook.gblExpressRateBook();
SoapContext requestContext = serviceProxy.RequestSoapContext;
requestContext.Security.Timestamp.TtlInSeconds = 60;
requestContext.Security.Tokens.Add(token);
//The rest of the logic goes here...
I added the screenshot down below for your reference:
NOTE: I was unable to test the code since I am unfamiliar with the actual methods that you need to consume, the code displayed is just an example of what I saw in the proxy class, update it according to your needs. It should work fine if you follow the steps described before. Check the following link for more detailed instructions:
https://msdn.microsoft.com/en-us/library/ms819938.aspx
You can configure you Service Reference to add the Security Header as AW Rowse describes at http://cxdeveloper.com/article/implementing-ws-security-digest-password-nonce-net-40-wcf:
private void Configure()
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => { return true; };
defaultBinding = new BasicHttpBinding
{
Security =
{
Mode = BasicHttpSecurityMode.Transport,
Transport =
{
ClientCredentialType = HttpClientCredentialType.Digest
}
}
};
defaultToken = new UsernameToken(UserName, Password, PasswordOption.SendHashed);
defaultSecurityHeader = MessageHeader.CreateHeader(
"Security",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
defaultToken.GetXml(new XmlDocument())
);
}
And create you client/proxy like this:
public consulta_informacao_respttClient CriaConsultaClinicaClient()
{
var client = new consulta_informacao_respttClient(defaultBinding, new EndpointAddress("https://resqa.homologacao.unimed.coop.br/chs-integration-external-services-ptu-clinical/proxy-services/execute-query/execute-query-proxy-service"));
client.ClientCredentials.UserName.UserName = UserName;
client.ClientCredentials.UserName.Password = Password;
var scope = new OperationContextScope(client.InnerChannel);
OperationContext.Current.OutgoingMessageHeaders.Add(defaultSecurityHeader);
return client;
}
The properties you will need to create in your class are:
private BasicHttpBinding defaultBinding;
private UsernameToken defaultToken;
private MessageHeader defaultSecurityHeader;
You won't need to configure anything in app/web.config.

Microsoft Fakes (Shims and / or Stubs) on a c# method with SQL code

I am trying to learn a bit more about Unit Testing, using out-of-the-box functionality (i believe it is MSTest.exe), and Microsoft Fakes (stubs and Shims).
I am using Visual Studio 2012 Ultimate and .Net 4.5 Framework.
Given the following code that calls a stored procedure (SQL Server) which returns a single output value (for simplicity):
public string GetSomeDatabaseValue()
{
string someValue = String.Empty;
SqlParameter paramater = new SqlParameter();
paramater.ParameterName = "#SomeParameter";
paramater.Direction = ParameterDirection.Output;
paramater.SqlDbType = SqlDbType.NVarChar;
paramater.Size = 50;
try
{
using(SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["connection"].ConnectionString))
{
using (SqlCommand command = new SqlCommand())
{
command.Connection = connection;
command.CommandType = System.Data.CommandType.StoredProcedure;
command.CommandText = "SomeStoredProcedure";
command.Parameters.Add(paramater);
connection.Open();
command.ExecuteNonQuery();
if (command.Parameters["#SomeParameter"] != null)
{
someValue= Convert.ToString(command.Parameters["#SomeParameter"].Value);
}
}
}
}
catch(SqlException)
{
throw;
}
return someValue;
}
Can it be tested using shims and/or stubs so that the output value can be set to a specific value?
If so how?
Should I even use unit testing for this?
I have followed this tutorial and managed to understand and adapt it to the day of the week.
I'm waiting on the VS2012 database unit tests functionality to become available by end of 2012 (or reinstated) as a MS employee has commented so that the database can be tested in isolation.
Microsoft Fakes is not an appropriate tool to test this code. Create an integration test instead. In this test, use a local instance of the SQL server, explicitly create data that the stored procedure expects to find in the database, call the stored procedure and verify its result. Rollback transaction or manually delete data from the database to ensure that it does not affect other tests.