Azure Web Job - Data Processing - asp.net-mvc

In VS I've created an Azure Web Job. I see a boiler plate method:
static void Main()
{
var host = new JobHost();
// The following code ensures that the WebJob will be running continuously
host.RunAndBlock();
}
Also a function method:
// This function will get triggered/executed when a new message is written
// on an Azure Queue called queue.
public static void ProcessQueueMessage([QueueTrigger("queue")] string message, TextWriter log)
{
log.WriteLine(message);
}
Cool... however I don't want to use Azure Queue or blog storage. I don't need to pass in any data as arguments or trigger it.
I simply want a job that will run every hour and do some data processing. Specially hit a 3rd party API and load some data into my Azure DB.
What am I missing here?
EDIT
Should I just be using a vanilla console app in this situation and publish it as an "Azure Web Job" ?

You should just use a vanilla console app and deploy that as an Azure Web Job. See the steps below:
Right-click the web project in Solution Explorer, and then click Add > Existing Project as Azure WebJob. The Add Azure WebJob dialog box appears.
In the Project name drop-down list, select the Console Application project to add as a WebJob.
Complete the Add Azure WebJob dialog, and then click OK.
The Publish Web wizard appears. If you don't want to publish immediately, close the wizard. The settings that you've entered are saved for when you do want to deploy the project.
Source with screenshots: https://azure.microsoft.com/nl-nl/documentation/articles/websites-dotnet-deploy-webjobs/#convert
You can find more information about this here: https://azure.microsoft.com/nl-nl/documentation/articles/websites-dotnet-deploy-webjobs/.
On this page you can also read that a console application can be used as an Azure Web Job by adding the Microsoft.Web.WebJobs.Publish NuGet package and a webjob-publish-settings.json.
Example webjob-publish-settings.json:
{
"$schema": "http://schemastore.org/schemas/json/webjob-publish-settings.json",
"webJobName": "WebJob1",
"startTime": "2014-06-23T00:00:00-08:00",
"endTime": "2014-06-27T00:00:00-08:00",
"jobRecurrenceFrequency": "Minute",
"interval": 5,
"runMode": "Scheduled"
}
When you want to add this Azure Web Job to an existing Azure Web App (website) project you can link the webjob by adding a webjobs-list.json file to the website project.
Example webjobs-list.json:
{
"$schema": "http://schemastore.org/schemas/json/webjobs-list.json",
"WebJobs": [
{
"filePath": "../ConsoleApplication1/ConsoleApplication1.csproj"
},
{
"filePath": "../WebJob1/WebJob1.csproj"
}
]
}

Related

Visual Studio 2019 Logic Apps Designer removing code

I have Visual Studio 2019 16.10.4 and Azure Logic Apps Tools for Visual Studio 2019 2.24.2
I have created a Logic App by first going to the portal and getting a simple skeleton trigger that listens on an Event Grid Topic and connects using a Managed Identity.
I then copy the json over to my Visual Studio project.
Once in Visual Studio if I deploy the ARM template (note I deploy the ARM template using a simple powershell script and not the one generated by the tool but that should not matter) everything works as I expect, I get the API Connection, Logic App, and Event Grid Trigger all created so I am happy that the contents of the ARM template and parameters file all work as I expect.
The issue I face is that when I open the Logic App in the Logic App designer the tool seems to remove the managed identity code from the json and then the tool spits out an error in the output window.
If I can try to explain.
This is the code in the raw json file before I open in the designer:
"$connections": {
"value": {
"azureeventgrid": {
"id": "[concat(subscription().id, '/providers/Microsoft.Web/locations/', parameters('LogicAppLocation'), '/managedApis/', 'azureeventgrid')]",
"connectionId": "[resourceId('Microsoft.Web/connections', parameters('azureeventgrid_1_Connection_Name'))]",
"connectionName": "[parameters('azureeventgrid_1_Connection_Name')]",
"connectionProperties": {
"authentication": {
"type": "ManagedServiceIdentity"
}
}
}
}
}
When I open in the designer I see this error message in the Output window:
The workflow connection parameter 'azureeventgrid' is not valid. The API connection 'azureeventgrid' is configured to support managed identity but the connection parameter is either missing 'authentication' property in connection properties or authentication type is not 'ManagedServiceIdentity'.
And then when I look at the raw json this is what now appears:
"$connections": {
"value": {
"azureeventgrid": {
"id": "[concat(subscription().id, '/providers/Microsoft.Web/locations/', parameters('LogicAppLocation'), '/managedApis/', 'azureeventgrid')]",
"connectionId": "[resourceId('Microsoft.Web/connections', parameters('azureeventgrid_1_Connection_Name'))]",
"connectionName": "[parameters('azureeventgrid_1_Connection_Name')]"
}
}
}
}
So it appears as if the tool is not happy with some part of my code and removes it.
I then do my work, close the designer, open the raw json, copy back in the removed connectionProperties and deploy. So I do have a workaround but it is a bit tedious to have to do this all the time.
Is this a known issue? For example I can see that the designer does not seem to allow me to create a logic app with a trigger to event grid that uses Managed Identity (hence why I started out by creating a skeleton in the portal and copying the code over).

TextRotation angle is never set in Google Sheet API

I'm using Google Sheets API v4 from Java Client. I'm trying to get format from Cell class. Everything goes fine.
TEXT ROTATION
I'm succeed in getting TextRotation element with Vertical property set but, angle property is never set, what ever I put on source Google Sheets document.
Whatever the angle value selected in Google Sheet App, angle property is never set.
I've tried to inspect returned JSON, to know if the issue is in Java Client.
But JSON REST API also never returns this property.
Current Result:
.
Expected Result:
Issue and workaround:
When I saw CellFormat of the official document, I thought that the value of textRotation can be retrieved by the fields of sheets(data(rowData(values(userEnteredFormat(textRotation))))) when the method of "spreadsheets.get" is used. But when I tested this, no values are returned. So I thought that this might be a bug. And, when I searched this at the Google issue tracker, I found https://issuetracker.google.com/issues/146274218. From this situation, in the current stage, it seems that the values of textRotation cannot be retrieved by the method of "spreadsheets.get" of Sheets API.
When you want to retrieve the value of textRotation using a script, as a current workaround, you can achieve it using the Web Apps created by Google Apps Script as a wrapper. In this answer, I would like to propose the workaround.
When this workaround is reflected to the flow for your situation, it becomes as follows.
Usage:
1. Create new project of Google Apps Script.
Sample script of Web Apps is a Google Apps Script. So please create a project of Google Apps Script.
If you want to directly create it, please access to https://script.new/. In this case, if you are not logged in Google, the log in screen is opened. So please log in to Google. By this, the script editor of Google Apps Script is opened.
2. Prepare Web Apps side. (server side)
Please copy and paste the following script (Google Apps Script) to the script editor. This script is for the Web Apps. This Web Apps is used as an API.
Server side: Google Apps Script
function doGet(e) {
const key = "sampleKey";
const id = e.parameter.spreadsheetId;
const sheetName = e.parameter.sheetName;
if (e.parameter.key != key || !id || !sheetName) {
return ContentService.createTextOutput(JSON.stringify({message: "Error."})).setMimeType(ContentService.MimeType.JSON);
}
const sheet = SpreadsheetApp.openById(id).getSheetByName(sheetName);
const textRotations = sheet.getDataRange().getTextRotations().map(r => r.map(c => ({angle: c.getDegrees(), vertical: c.isVertical()})));
return ContentService.createTextOutput(JSON.stringify(textRotations)).setMimeType(ContentService.MimeType.JSON);
}
3. Deploy Web Apps.
On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".
Select "Me" for "Execute the app as:".
By this, the script is run as the owner.
Select "Anyone, even anonymous" for "Who has access to the app:".
Of course, you can use the access token for this situation. But in this case, as a simple setting, I use the access key instead of the access token.
Click "Deploy" button as new "Project version".
Automatically open a dialog box of "Authorization required".
Click "Review Permissions".
Select own account.
Click "Advanced" at "This app isn't verified".
Click "Go to ### project name ###(unsafe)"
Click "Allow" button.
Click "OK".
Copy the URL of Web Apps. It's like https://script.google.com/macros/s/###/exec.
When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
3. Testing.
As a simple test, when it requests to the Web Apps using a curl command, it becomes as follows. Please set the spreadsheet ID and sheet name. When the Web Apps is correctly deployed, the values are returned.
$ curl -L "https://script.google.com/macros/s/###/exec?spreadsheetId=###&sheetName=Sheet1&key=sampleKey"
Result:
The data range is used for retrieving the values. So for example, when the values are set to the cells "A1:C3" in "Sheet1", the following result is returned.
[
[{"angle":30,"vertical":false},{"angle":0,"vertical":true},{"angle":0,"vertical":false}],
[{"angle":30,"vertical":false},{"angle":30,"vertical":false},{"angle":0,"vertical":false}]
]
In this case, the cells "A1, A2, B2" have the text rotation with 30 degree. And, the cell "B1" has the vertical direction.
Note:
When you modified the script of Web Apps, please redeploy the Web Apps as new version. By this, the latest script is reflected to Web Apps. Please be careful this.
References:
CellFormat
getTextRotations()
Web Apps
Taking advantage of Web Apps with Google Apps Script
Finally, I've written a JS Library : screen-rotation.js to manage all this stuff.
screenorientation().change(function(){
// My event management
});
It supports iOS, Android & desktop browsers

Possible to create Team Foundation Server Project programmatically?

I need to create Team Foundation Server projects, but the only way I can find to do it is manually through the website.
Is it possible to do programmatically via a CLI, programming language, or RESTful API?
Thanks in advance.
Is it possible to do programmatically via a CLI, programming language,
or RESTful API?
It's possible, you can do that using Rest API. Azure Devops Server 2019 and TFS 2018U2 both support creating project using Rest API. TFS2018U2, Azure Devops Server.
More details please refer to this document.
Test with TFS2018U2 in PostMan:
Request URL: https://ServerName:8080/tfs/CollectionName/_apis/projects?api-version=4.1
Request Body:
{
"name": "CreateProjectTest",
"description": "Just for Test",
"capabilities": {
"versioncontrol": {
"sourceControlType": "Git"
},
"processTemplate": {
"templateTypeId": "6b724908-ef14-45cf-84f8-768b5384da45"
}
}
}
If you get status 202 accepted, then you can see the newly created project in website after some time (For me,10~25 seconds).
Note: The document states the format is https://{instance}/{collection}/_apis/projects?api-version=xxx, but you need to use http instead of https when you Public URL starts with http:
In addition: Here's one similar issue to achieve what you want using CLI. And here's another one that may give you some hint if you want to do that using C# code.
Hope all above helps :)

Creating and deploying a windows service publishing pages in SDL Tridion

Our requirement is to schedule content publishing of a content page to run in recurring intervals in Tridion CMS application. We are currently using Tridion 2009 SP1 version.
As per the suggestion from the experts as in: Tridion 2009 SP1: How to schedule a content page for a recurring publishing? we have created a simple C# console application that has referenced Triond Interop .dll's as below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tridion.ContentManager.Interop.TDS;
using Tridion.ContentManager.Interop.TDSDefines;
using Tridion.ContentManager.Interop.msxml4;
using System.Configuration;
namespace SchedulePublish
{
class Program
{
static void Main(string[] args)
{
//Please use your system related corresponding webdav url's and tcm id's where ever required. Below are just sample :)
TDSE tdse = new TDSE();
//Give some identity that has access rights on tridion UI
string Identity = #"Domain Name\Username";
tdse.Impersonate(Identity);
tdse.Initialize();
string targetTypeId = "tcm:0-1-65537";
Publication Pub_Obj = (Publication)tdse.GetPublication("/webdav/30%20DIRECTV%20sites");
XMLReadFilter Filter = new XMLReadFilter();
Component CompObj = (Component)tdse.GetObject("/webdav/30%20DIRECTV%20sites/Home/System/xml/Knavigation.xml",
EnumOpenMode.OpenModeView, Pub_Obj.ID, Filter);
DateTime schedulePublishDate = Convert.ToDateTime(ConfigurationManager.AppSettings["SharedPath"].ToString());
CompObj.Publish(targetTypeId, false, false, false, schedulePublishDate, DateTime.MinValue, DateTime.Now, true, EnumPublishPriority.High, false, 3);
}
}
}
As we are new, please provide pointers to implement the below steps:
1.Tridion CMS servers do not have Visual studio installed so please suggest a way to run this application and verify if we are able to publish the content as required.
2.Host this application in the Tridion CMS Server and schedule it to run at the desired intervals every week.
You don't need Visual Studio to run your new console app, simply compile it and copy the files to the CMS server.
If you run the application, you should see items appearing in your Publication Queue, if you don't see your items added to the Publish Queue, I would recommend adding some logging calls to your application so you can see where the code is failing (consider using Log4J.NET if you have not done logging before).
Once you have validated that it works as desired, the easiest way to schedule it is to create a task using the Windows Task Scheduler. There is no way to run such a task from within the CMS. Alternatively you could convert your console app to a windows service, but I think this would be overkill in this case.

Is it possible to debug the Quartz.NET Windows service?

I've got my app code in one solution and the Quartz.Net code in another. My app code connects to the service and registers a job but no break points are hit in the Quartz.NET solution despite the Visual Studio instance for the Quartz.Net code being attached to the service process. (Out of interest, when registering the job in my app, I can step into the Quartz.Net source code. It loads the source into my app's instance of Visual Studio.)
If I attach the debugger to the service process from the Visual Studio instance that contains my app code then a break point in my custom job source code says that the symbols haven't been loaded and so won't break. The dll that contains the custom job is not in the list of modules.
Any ideas? What I'm after is debugging my custom job that's loaded by the service when it starts. The dll that contains the custom job I've copied into the same folder as the Quartz.net bin directory and is definitely loaded OK because the job actually runs!
Cheers, Ian.
Have you also copied the custom job .pdb file?
you could also change the build destination to be in the Quartz.Net folder, no need to keep copy files around.
The way I do this is have a bit of code to the start of the job like :
if (System.Diagnostics.Debugger.IsAttached)
System.Diagnostics.Debugger.Break();
Then I open Visual Studio and attach the debugger to the Quartz.Net service. When the job starts, it will break into the debugger and I can then add breakpoints at other places.
What I would do is to create an Asp.Net core console application and with the application executable file I will create a Windows Service using sc. Below is my Program class.
using Backup.Service.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Backup.Service
{
public class Program
{
static async Task Main(string[] args)
{
var isDebugging = !(Debugger.IsAttached || args.Contains("--console"));
var hostBuilder = new HostBuilder()
.ConfigureServices((context, services) =>
{
services.AddHostedService<BackupService>();
});
if (isDebugging)
{
await hostBuilder.RunTheServiceAsync();
}
else
{
await hostBuilder.RunConsoleAsync();
}
}
}
}
If we are running the application locally/debug, we are calling the extension method RunConsoleAsync() or else we call our own custom extension method RunTheServiceAsync().
I had written a complete article on this topic, you can read it here. You can also see the complete source code in the GitHub here.

Resources