зеркало из
1
0
Форкнуть 0

Initial parsing service and bot service commit.

This commit is contained in:
Jason Barnwell (CELA) 2019-03-30 21:35:57 -07:00
Родитель 0962648b1d
Коммит 6c5519ddb4
241 изменённых файлов: 77308 добавлений и 0 удалений

63
.gitattributes поставляемый Normal file
Просмотреть файл

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

1
.gitignore поставляемый
Просмотреть файл

@ -328,3 +328,4 @@ ASALocalRun/
# MFractors (Xamarin productivity tool) working folder
.mfractor/
CELA-Tag_Parsing_Service_Configuration_Utilities/CELA_Tag_Services_Deployment_Configurations.json

Просмотреть файл

@ -0,0 +1,2 @@
[config]
command = deploy.cmd

5
CELA-Knowledge_Management_Assistant/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
*.dll
*.pdb
obj/**
bin/**
runtimes/**

Двоичные данные
CELA-Knowledge_Management_Assistant/BasicBot.cs Normal file

Двоичный файл не отображается.

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Microsoft Managed Recommended Rules" Description="These rules focus on the most critical problems in your code, including potential security holes, application crashes, and other important logic and design errors. It is recommended to include this rule set in any custom rule set you create for your projects." ToolsVersion="15.0">
<Localization ResourceAssembly="Microsoft.VisualStudio.CodeAnalysis.RuleSets.Strings.dll" ResourceBaseName="Microsoft.VisualStudio.CodeAnalysis.RuleSets.Strings.Localized">
<Name Resource="MinimumRecommendedRules_Name" />
<Description Resource="MinimumRecommendedRules_Description" />
</Localization>
<Rules AnalyzerId="AsyncUsageAnalyzers" RuleNamespace="AsyncUsageAnalyzers">
<Rule Id="AvoidAsyncVoid" Action="Warning" />
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1011" Action="None" />
<Rule Id="SA1101" Action="None" />
<Rule Id="SA1129" Action="None" />
<Rule Id="SA1200" Action="None" />
<Rule Id="SA1305" Action="Warning" />
<Rule Id="SA1309" Action="None" />
<Rule Id="SA1412" Action="Warning" />
<Rule Id="SA1600" Action="None" />
<Rule Id="SA1609" Action="Warning" />
<Rule Id="SA1633" Action="None" />
</Rules>
</RuleSet>

Просмотреть файл

@ -0,0 +1,12 @@
{
"runtimeOptions": {
"tfm": "netcoreapp2.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "2.0.0"
},
"configProperties": {
"System.GC.Server": true
}
}
}

Просмотреть файл

@ -0,0 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.2043
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CELA-Knowledge_Management_Assistant", "CELA-Knowledge_Management_Assistant.csproj", "{D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A7450314-AAE3-4639-8B12-558699156494}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License
using System;
using System.Collections.Generic;
using Microsoft.Bot.Builder.AI.Luis;
using Microsoft.Bot.Configuration;
namespace CELA_Knowledge_Management_Agent
{
/// <summary>
/// Represents references to external services.
///
/// For example, LUIS services are kept here as a singleton. This external service is configured
/// using the <see cref="BotConfiguration"/> class.
/// </summary>
/// <seealso cref="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1"/>
/// <seealso cref="https://www.luis.ai/home"/>
public class BotServices
{
/// <summary>
/// Initializes a new instance of the <see cref="BotServices"/> class.
/// </summary>
/// <param name="luisServices">A dictionary of named <see cref="LuisRecognizer"/> instances for usage within the bot.</param>
public BotServices(BotConfiguration botConfiguration)
{
foreach (var service in botConfiguration.Services)
{
switch (service.Type)
{
case ServiceTypes.Luis:
{
var luis = (LuisService)service;
if (luis == null)
{
throw new InvalidOperationException("The LUIS service is not configured correctly in your '.bot' file.");
}
var endpoint = (luis.Region?.StartsWith("https://") ?? false) ? luis.Region : luis.GetEndpoint();
var app = new LuisApplication(luis.AppId, luis.AuthoringKey, endpoint);
var recognizer = new LuisRecognizer(app);
this.LuisServices.Add(luis.Name, recognizer);
break;
}
}
}
}
/// <summary>
/// Gets the set of LUIS Services used.
/// Given there can be multiple <see cref="LuisRecognizer"/> services used in a single bot,
/// LuisServices is represented as a dictionary. This is also modeled in the
/// ".bot" file since the elements are named.
/// </summary>
/// <remarks>The LUIS services collection should not be modified while the bot is running.</remarks>
/// <value>
/// A <see cref="LuisRecognizer"/> client instance created based on configuration in the .bot file.
/// </value>
public Dictionary<string, LuisRecognizer> LuisServices { get; } = new Dictionary<string, LuisRecognizer>();
}
}

Просмотреть файл

@ -0,0 +1,46 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<CodeAnalysisRuleSet>BasicBot.ruleset</CodeAnalysisRuleSet>
<RootNamespace>CELA_Knowledge_Management_Assistant</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" />
<PackageReference Include="Microsoft.Azure.CognitiveServices.ContentModerator" Version="0.12.1-preview" />
<PackageReference Include="Microsoft.Azure.CognitiveServices.Language" Version="1.0.1-preview" />
<PackageReference Include="Microsoft.Bot.Builder" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder.AI.Luis" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder.Azure" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Configuration" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Connector" Version="4.1.5" />
<PackageReference Include="Microsoft.Bot.Schema" Version="4.1.5" />
<PackageReference Include="Microsoft.Graph" Version="1.10.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta008">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CELA-Knowledge_Management_Data_Services\CELA-Knowledge_Management_Data_Services.csproj" />
<ProjectReference Include="..\CELA-Tags_Parsing_Service\CELA-Tags_Parsing_Service.csproj" />
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Connected Services" />
</ItemGroup>
<ItemGroup>
<None Update="*.bot">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="PostDeployScripts\IncludeSources.targets" Condition="Exists('PostDeployScripts\IncludeSources.targets')" />
<Import Project="..\PostDeployScripts\IncludeSources.targets" Condition="Exists('..\PostDeployScripts\IncludeSources.targets')" />
</Project>

Просмотреть файл

@ -0,0 +1,62 @@
# How To Deploy
This bot relies on the [LUIS.ai][1] cognitive service to function. This document will show how to use simple command line tools to setup LUIS for use with this bot.
# Install required tools
To successfully setup and configure the services this bot depends on, you need to install the MSBOT, LUIS, and Ludown CLI tools. See the documentation for the [Bot Framework CLI Tools][5] for additional information on what CLI tools are available to help you build your bot.
Ensure you have [Node.js](https://nodejs.org/) version 8.5 or higher
```bash
npm i -g msbot luis-apis ludown
```
# Keeping track of service references using .bot file
We highly recommend you can keep track of all the services your bot depends on in a .bot file. You can use either the `msbot` CLI tool or use [Bot Framework Emulator][7] to manage your .bot file. This project was created with a bot file named [`basic-bot.bot`](../basic-bot.bot)
# Configure all required servies
You can use [MSBOT][5] to create and configure the required services for this bot. To do this, simply run the following command from a terminal.
You can get your LUIS authoring key by following steps [here][8] and get your Azure subscription ID by following steps [here][9].
```bash
> cd samples/javascript_nodejs/13.basic-bot
> msbot clone -n <YOUR BOT NAME> -f deploymentScripts/msbotClone --luisAuthoringKey <LUIS-KEY> --subscriptionId <AZURE-SUBSCRIPTION-ID>
```
# Using the CLI tools to create and configure services
The LUIS application created for this bot is described in a markdown based .lu file(s) [here](../dialogs/greeting/resources/main.lu). To update your published LUIS application with any changes made to the .lu files, run the following commands.
```bash
> cd samples/javascript_nodejs/13.basic-bot
```
1. To parse the .lu files to a LUIS model:
```bash
> ludown parse toluis --in dialogs/greeting/resources/main.lu -o cognitiveModels/ --out basicBot.luis -n 'basic-bot-LUIS' -d 'Basic bot Bot Builder V4 sample.' --verbose
```
2. To create a new LUIS application using the LUIS model generated in step 1 and update the .bot file with the LUIS service configuration:
```bash
> luis import application --in cognitiveModels/basicBot.luis --authoringKey <YOUR-LUIS-AUTHORING-KEY> --msbot --endpointRegion --region <LUIS-AUTHORING-REGION> | msbot connect luis --stdin
```
You can obtain your LUIS authoring key by following instructions [here][8]
LUIS authoring regions are listed [here][10]. They can be one of westus | westeurope | australiaeast.
3. To train the LUIS application,
```bash
> msbot get basic-bot-LUIS | luis train version --wait --stdin
```
4. To publish the LUIS application,
```bash
> msbot get basic-bot-LUIS | luis publish version --stdin
```
See [Bot Builder tools](https://github.com/microsoft/botbuilder-tools) to learn more about the Bot Builder CLI tools.
[1]: https://www.luis.ai
[2]: https://docs.microsoft.com/en-us/azure/bot-service/bot-service-concept-intelligence
[3]: https://portal.azure.com
[4]: https://azure.microsoft.com/en-us/get-started/
[5]: https://github.com/microsoft/botbuilder-tools
[6]: https://dev.botframework.com
[7]: https://www.github.com/microsoft/botframework-emulator
[8]: https://docs.microsoft.com/en-us/azure/cognitive-services/luis/luis-how-to-account-settings
[9]: https://blogs.msdn.microsoft.com/mschray/2016/03/18/getting-your-azure-subscription-guid-new-portal/

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace CELA_Knowledge_Management_Agent
{
/// <summary>
/// User state properties for Greeting.
/// </summary>
public class GreetingState
{
public string Name { get; set; }
public string City { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,19 @@
> Cancel intent and utterances
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
# Cancel
- please cancel
- cancel
- quit
- stop
- abort
- don't do it
- don't do that
- i would like to cancel
- i will not give you my name
- i won't give you my name
- no way, I won't give you my location
- I'm not going to tell you where i live
- I will not give you my location or name
- no way
- please stop
- I'm bailing

Просмотреть файл

@ -0,0 +1,9 @@
user=Vishwac
bot=BasicBot
user: hi
bot: What is your name?
user: my name is vishwac
bot: Hello Vishwac, what city do you live in?
user: I'm from seattle
bot: Hi Vishwac, from Seattle, nice to meet you!

Просмотреть файл

@ -0,0 +1,61 @@
> Greeting intent and utterances
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
# Greeting
- good evening
- good morning
- hello
- hello bot
- hey
- hey there
- hi
- hi bot
- hiya
- how are you
- how are you today
- what's your name
- who am i speaking to
- who am i speaking with
- who are you
- yo
> Add utterances with machine learned simple entity values
- call me {userName=scott}
- {userName=dan}
- {userLocation=delhi}
- {userLocation=dhaka}
- i live in {userLocation=london}
- i reside in {userLocation=san francisco}
- i'm from {userLocation=georgia}
- i'm {userName=john} from {userLocation=cairo}
- i'm {userName=lauren}, and i'm from {userLocation=madrid}
- i'm {userName=lili}
- {userName=melanie}
- {userLocation=mumbai}
- my location is {userLocation=new york}
- my name is {userName=maria} and i'm from {userLocation=sydney}
- my name is {userName=tom}
- {userLocation=paris}
- {userLocation=portland}
- {userLocation=seattle} is my current city
- {userLocation=shangai}
- {userName=tony} is my name
- {userLocation=toronto}
- {userName=vishwac} is my name
- you can assume i live in {userLocation=cairo}
- you can call me {userName=steve}
> Add patterns with pattern.any entitiy
- some people call me {userName_patternAny}
- {userName_patternAny}.
- i'm {userName_patternAny}
- {userName_patternAny} is my name
- my name is {userName_patternAny} and i'm from {userLocation_patternAny}
- {userLocation_patternAny} is where i live
- i'm from {userLocation_patternAny}
- my name is {userName_patternAny}
- i reside in {userLocation_patternAny}
- you can call me {userName_patternAny}
- you can assume i live in {userLocation_patternAny}
- call me {userName_patternAny}
- i live in {userLocation_patternAny}
- i'm {userName_patternAny}[,] [and i'm] from {userLocation_patternAny}

Просмотреть файл

@ -0,0 +1,22 @@
> Help intent and utterances
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
# Help
- what can you do
- ?
- I'm lost
- lost
- confused
- frustrated
- what are your capabilities
- help me
- help
- how do I interact with you
- help please
- i'm stuck
- i don't understand
- what can I say
- what can you help me with
- what can you do
- what do i do now
- why doesn't this work
- can you help me

Просмотреть файл

@ -0,0 +1,3 @@
> Reference to other .lu files
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
[All intents](./*)

Просмотреть файл

@ -0,0 +1,21 @@
> None intent and example utterances
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
# None
- spaghetti
- gnocchi
- her cat has no teeth
- world wide pants
- i'd rather be riding my bike
- Cook me something
- Have you any dreams?
- Dont you ever sleep?
- Do you play games?
- Can you fly?
- What's your age?
- Are you old?
- How old are you?
- Getting tired of you
- I am tired of you
- You are boring
- Who is your boss?
- Are you busy?

Просмотреть файл

@ -0,0 +1,46 @@
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Image",
"url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU",
"size": "stretch"
},
{
"type": "TextBlock",
"spacing": "medium",
"size": "default",
"weight": "bolder",
"text": "Welcome to Bot Framework!",
"wrap": true,
"maxLines": 0
},
{
"type": "TextBlock",
"size": "default",
"isSubtle": "yes",
"text": "Now that you have successfully run your bot, follow the links in this Adaptive Card to expand your knowledge of Bot Framework.",
"wrap": true,
"maxLines": 0
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Get an overview",
"url": "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"
},
{
"type": "Action.OpenUrl",
"title": "Ask a question",
"url": "https://stackoverflow.com/questions/tagged/botframework"
},
{
"type": "Action.OpenUrl",
"title": "Learn how to deploy",
"url": "https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"
}
]
}

Просмотреть файл

@ -0,0 +1,12 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CoreCompileDependsOn>$(CoreCompileDependsOn);IncludeSource</CoreCompileDependsOn>
</PropertyGroup>
<Target Name="IncludeSource">
<ItemGroup>
<Content Include="**\*.cs" />
<Content Include="**\*.csproj" />
<Content Include="PostDeployScripts\*.*" />
</ItemGroup>
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,9 @@
{
"name": "{WEB_SITE_NAME}",
"description": "{WEB_SITE_NAME} Azure Bot Service Code",
"homepage": "https://github.com",
"private": false,
"has_issues": true,
"has_projects": true,
"has_wiki": true
}

Просмотреть файл

@ -0,0 +1,59 @@
const fs = require('fs');
const path = require('path');
const appSettingPath = path.resolve('./appsettings.json');
const envPath = path.resolve('./.env');
const settings = readSettingsFile(appSettingPath, envPath);
const env = process.env;
const envNames = Object.keys(env)
.filter(function(x){ return x.indexOf("APPSETTING_") === 0;})
.filter(function(x){ return x.indexOf("APPSETTING_WEBSITE_") < 0; });
const appSettings = envNames.reduce(function(cur, key) { return {...cur, [key.substring(11)]: env[key]};}, {});
const newSettings = {...settings, ...appSettings};
updateSettingsFile(appSettingPath, envPath, newSettings);
function readDotEnv(file) {
const text = fs.readFileSync(file, 'utf-8');
const lines = text.split(/[\r\n]/);
const settings = lines.reduce(function(cur, line) {
const parts = line.split('=');
if (parts.length >= 2) {
const name = parts.splice(0, 1);
cur[name] = parts.join('=');
}
return cur;
}, {});
return settings;
}
function readSettingsFile(appSettingPath, envPath) {
if (fs.existsSync(appSettingPath)) {
return JSON.parse(fs.readFileSync(appSettingPath, 'utf-8'));
}
if (fs.existsSync(envPath)) {
return readDotEnv(envPath);
}
return {};
}
function isNodeJSProject() {
return fs.existsSync(path.resolve('./iisnode.yml'));
}
function updateSettingsFile(appSettingPath, envPath, settings) {
if (isNodeJSProject()) {
const keys = Object.keys(settings);
const lines = keys.reduce(function(cur, key) {
return [...cur, key + '=' + settings[key]];
}, []);
fs.writeFileSync(envPath, lines.join('\n'), {encoding: 'utf-8'});
} else {
fs.writeFileSync(appSettingPath, JSON.stringify(settings, null, 2), {encoding: 'utf-8'});
}
}

Просмотреть файл

@ -0,0 +1,88 @@
@echo off
setlocal
SET password=%1
SET exportSettings=%2
SET repoName=srcRepo
SET repoUrl=file:///%HOMEDRIVE:~0,1%/%HOMEPATH:~1%/site/%repoName%
SET download=bot-src
echo %repoUrl%
rem cd to project root
pushd ..\wwwroot
rem init git
call git init
call git config user.name "botframework"
call git config user.email "util@botframework.com"
call git add .
call git commit -m "prepare to download source"
call git remote add srcRepo %repoUrl%
popd
rem init upstream
pushd %HOME%\site
mkdir srcRepo
cd srcRepo
call git init --bare
popd
rem push to upstream
pushd ..\wwwroot
call git push --set-upstream srcRepo master
popd
rem clone srcRepo
pushd %HOME%\site
call git clone %repoUrl% %download%
rem delete .git
cd %download%
call rm -r -f .git
popd
rem prepare for publish
pushd %HOME%\site\%download%
mkdir Properties\PublishProfiles
pushd Properties\PublishProfiles
type ..\..\PostDeployScripts\publishProfile.xml.template | sed -e s/\{WEB_SITE_NAME\}/%WEBSITE_SITE_NAME%/g > %WEBSITE_SITE_NAME%-Web-Deploy.pubxml
popd
set SOLUTION_NAME=
for /f "delims=" %%a in ('dir /b *.sln') do @set SOLUTION_NAME=%%a
type PostDeployScripts\publish.cmd.template | sed -e s/\{SOLUTION_NAME\}/%SOLUTION_NAME%/g | sed -e s/\{PUBLISH_PROFILE\}/%WEBSITE_SITE_NAME%-Web-Deploy.pubxml/g | sed -e s/\{PASSWORD\}/%password%/g > publish.cmd
type PostDeployScripts\publishSettings.xml.template | sed -e s/\{WEB_SITE_NAME\}/%WEBSITE_SITE_NAME%/g | sed -e s/\{PASSWORD\}/%password%/g > PostDeployScripts\%WEBSITE_SITE_NAME%.PublishSettings
popd
echo %exportSettings%
if "%exportSettings%" == "" goto zip
pushd %HOME%\site\%download%
echo 'export app settings'
call :APP_SETTINGS
popd
:zip
rem preare the zip file
%HOMEDRIVE%\7zip\7za a %HOME%\site\%download%.zip %HOME%\site\%download%\*
rem cleanup git stuff
pushd ..\wwwroot
call rm -r -f .git
popd
pushd %HOME%\site
call rm -r -f %download%
call rm -r -f %repoName%
popd
endlocal
goto :EOF
:APP_SETTINGS
echo 'dump app settings'
node %HOME%\site\wwwroot\PostDeployScripts\mergeSettings.js
exit /b

Просмотреть файл

@ -0,0 +1,3 @@
nuget restore
msbuild {SOLUTION_NAME} -p:DeployOnBuild=true -p:PublishProfile={PUBLISH_PROFILE} -p:Password={PASSWORD}

Просмотреть файл

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>MSDeploy</WebPublishMethod>
<PublishProvider>AzureWebSite</PublishProvider>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish>http://{WEB_SITE_NAME}.azurewebsites.net</SiteUrlToLaunchAfterPublish>
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<MSDeployServiceURL>{WEB_SITE_NAME}.scm.azurewebsites.net:443</MSDeployServiceURL>
<DeployIisAppPath>{WEB_SITE_NAME}</DeployIisAppPath>
<RemoteSitePhysicalPath />
<SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
<MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
<EnableMSDeployBackup>True</EnableMSDeployBackup>
<UserName>${WEB_SITE_NAME}</UserName>
<_SavePWD>True</_SavePWD>
<_DestinationType>AzureWebSite</_DestinationType>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,15 @@
<publishData>
<publishProfile profileName="{WEB_SITE_NAME}-Web-Deploy"
publishMethod="MSDeploy"
publishUrl="{WEB_SITE_NAME}.scm.azurewebsites.net:443"
msdeploySite="{WEB_SITE_NAME}" userName="${WEB_SITE_NAME}"
userPWD="{PASSWORD}"
destinationAppUrl="http://{WEB_SITE_NAME}.azurewebsites.net"
SQLServerDBConnectionString=""
mySQLDBConnectionString=""
hostingProviderForumLink=""
controlPanelLink="http://windows.azure.com"
webSystem="WebSites">
<databases />
</publishProfile>
</publishData>

Просмотреть файл

@ -0,0 +1,23 @@
@echo off
setlocal
set DEPLOYMENT_SOURCE=
set IN_PLACE_DEPLOYMENT=1
if exist ..\wwwroot\deploy.cmd (
pushd ..\wwwroot
call deploy.cmd
popd
)
rem kick of build of csproj
echo record deployment timestamp
date /t >> ..\deployment.log
time /t >> ..\deployment.log
echo ---------------------- >> ..\deployment.log
echo Deployment done
endlocal

Просмотреть файл

@ -0,0 +1,44 @@
@echo off
setlocal
rem ------------------------------------------------------------------------------------------
rem setupVsoRemoteRepo [remoteUser] [personalAccessToken] [projName{optional}]
rem create and populate VSO git repo for the ABS code instance
rem
rem remoteUser: user account name of the personal access token
rem personalAccessToken: the personal access token used to access github REST API (requires repos scope)
rem projName the name of the project to create (default to WEBSITE_SITE_NAME)
rem ------------------------------------------------------------------------------------------
set remoteUrl=https://api.github.com
set remoteUser=%1
set remotePwd=%2
set projName=%3
if '%projName%'=='' set projName=%WEBSITE_SITE_NAME%
set repoUrl=https://%remoteUser%:%remotePwd%@github.com/%remoteUser%/%projName%.git
rem use curl to create project
pushd ..\wwwroot
type PostDeployScripts\githubProject.json.template | sed -e s/\{WEB_SITE_NAME\}/%projName%/g > %TEMP%\githubProject.json
call curl -H "Content-Type: application/json" -u %remoteUser%:%remotePwd% -d "@%TEMP%\githubProject.json" -X POST %remoteUrl%/user/repos
rem rm %TEMP%\githubProject.json
popd
popd
rem cd to project root
pushd ..\wwwroot
rem init git
call git init
call git config user.name "%remoteUser%"
call git config user.password "%remotePwd%"
call git config user.email "util@botframework.com"
call git add .
call git commit -m "prepare to setup source control"
call git push %repoUrl% master
popd
rem cleanup git stuff
pushd ..\wwwroot
call rm -r -f .git
popd
endlocal

Просмотреть файл

@ -0,0 +1,50 @@
@echo off
setlocal
rem ------------------------------------------------------------------------------------------
rem setupVsoRemoteRepo [vsoRemote] [vsoUserName] [vsoPersonalAccessToken] [projName{optional}]
rem create and populate VSO git repo for the ABS code instance
rem
rem vsoRmote: url of the VSO site (e.g. https://awesomebot.visualstudio.com )
rem vosUserName: user account name of the personal access token
rem vsoPersonalAccessToken: the personal access token used to access VSO REST api
rem projName the name of the project to create (default to WEBSITE_SITE_NAME)
rem ------------------------------------------------------------------------------------------
set remoteUrl=%1
set remoteUser=%2
set remotePwd=%3
set projName=%4
if '%projName%'=='' set projName=%WEBSITE_SITE_NAME%
set vstsRoot=%remoteUrl%
set repoUrl=https://%remoteUser%:%remotePwd%@%remoteUrl:~8%/_git/%projName%
set vstsCreateProject=https://%remoteUser%:%remotePwd%@%remoteUrl:~8%/defaultcollection/_apis/projects?api-version=3.0
rem use curl to create project
pushd ..\wwwroot
type PostDeployScripts\vsoProject.json.template | sed -e s/\{WEB_SITE_NAME\}/%projName%/g > %TEMP%\vsoProject.json
call curl -H "Content-Type: application/json" -d "@%TEMP%\vsoProject.json" -X POST %vstsCreateProject%
rm %TEMP%\vsoProject.json
rem sleep for 15 seconds for the creation to complete, this is a wild guess
call sleep 15
popd
popd
rem cd to project root
pushd ..\wwwroot
rem init git
call git init
call git config user.name "%remoteUser%"
call git config user.password "%remotePwd%"
call git config user.email "util@botframework.com"
call git add .
call git commit -m "prepare to setup source control"
call git push %repoUrl% master
popd
rem cleanup git stuff
pushd ..\wwwroot
call rm -r -f .git
popd
endlocal

Просмотреть файл

@ -0,0 +1,12 @@
{
"name": "{WEB_SITE_NAME}",
"description": "{WEB_SITE_NAME} Azure Bot Service Code",
"capabilities": {
"versioncontrol": {
"sourceControlType": "Git"
},
"processTemplate": {
"templateTypeId": "6b724908-ef14-45cf-84f8-768b5384da45"
}
}
}

Просмотреть файл

@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
namespace CELA_Knowledge_Management_Agent
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
// Add Azure Logging
logging.AddAzureWebAppDiagnostics();
// Other Loggers.
// There are other logging options available:
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-2.1
// logging.AddDebug();
// logging.AddConsole();
})
// Application Insights.
// An alternative logging and metrics service for your application.
// https://azure.microsoft.com/en-us/services/application-insights/
// .UseApplicationInsights()
.UseStartup<Startup>()
.Build();
}
}

Просмотреть файл

@ -0,0 +1,67 @@
# Basic Bot template
This bot has been created using [Microsoft Bot Framework](https://dev.botframework.com),
- Use [LUIS](https://luis.ai) to implement core AI capabilities
- Implement a multi-turn conversation using Dialogs
- Handle user interruptions for such things as Help or Cancel
- Prompt for and validate requests for information from the user
# Prerequisite to run this bot locally
- Download the bot code from the Build blade in the Azure Portal
- Update the `appsettings.json` file in the root of the bot project with the botFilePath and botFileSecret
- You can find the botFilePath and botFileSecret in the Azure App Service application settings.
Your appsettings.json file should look like this
```bash
{
"botFilePath": "<copy value from App settings>",
"botFileSecret": "<copy value from App settings>"
}
```
## Run in Visual Studio
- Open the .sln file with Visual Studio.
- Press F5.
## Run in Visual Studio Code
- Open the bot project folder with Visual Studio Code.
- Bring up a terminal.
- Type 'dotnet run'.
## Testing the bot using Bot Framework Emulator
[Microsoft Bot Framework Emulator](https://aka.ms/botframework-emulator) is a desktop application that allows bot developers to test and debug
their bots on localhost or running remotely through a tunnel.
- Install the Bot Framework Emulator from [here](https://aka.ms/botframework-emulator).
### Connect to bot using Bot Framework Emulator
- Launch the Bot Framework Emulator
- File -> Open bot and navigate to the bot project folder
- Select `<your-bot-name>.bot` file
# Deploy this bot to Azure
## Publish from Visual Studio
- Open the .PublishSettings file you find in the PostDeployScripts folder
- Copy the userPWD value
- Right click on the Project and click on "Publish..."
- Paste the password you just copied and publish
## Publish using the CLI tools
You can use the [MSBot](https://github.com/microsoft/botbuilder-tools) Bot Builder CLI tool to clone and configure any services this sample depends on.
To install all Bot Builder tools -
Ensure you have [Node.js](https://nodejs.org/) version 8.5 or higher
```bash
npm i -g msbot chatdown ludown qnamaker luis-apis botdispatch luisgen
```
To clone this bot, run
```
msbot clone services -f deploymentScripts/msbotClone -n <BOT-NAME> -l <Azure-location> --subscriptionId <Azure-subscription-id>
```
# Further reading
- [Bot Framework Documentation](https://docs.botframework.com)
- [Bot basics](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)
- [LUIS](https://luis.ai)
- [Prompt Types](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-prompts?view=azure-bot-service-4.0&tabs=javascript)
- [Azure Bot Service Introduction](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
- [QnA Maker](https://qnamaker.ai)

Просмотреть файл

@ -0,0 +1,19 @@
> Cancel intent and utterances
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
# Cancel
- please cancel
- cancel
- quit
- stop
- abort
- don't do it
- don't do that
- i would like to cancel
- i will not give you my name
- i won't give you my name
- no way, I won't give you my location
- I'm not going to tell you where i live
- I will not give you my location or name
- no way
- please stop
- I'm bailing

Просмотреть файл

@ -0,0 +1,9 @@
user=Vishwac
bot=BasicBot
user: hi
bot: What is your name?
user: my name is vishwac
bot: Hello Vishwac, what city do you live in?
user: I'm from seattle
bot: Hi Vishwac, from Seattle, nice to meet you!

Просмотреть файл

@ -0,0 +1,19 @@
> Greeting intent and utterances
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
# Greeting
- good evening
- good morning
- hello
- hello bot
- hey
- hey there
- hi
- hi bot
- hiya
- how are you
- how are you today
- what's your name
- who am i speaking to
- who am i speaking with
- who are you
- yo

Просмотреть файл

@ -0,0 +1,22 @@
> Help intent and utterances
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
# Help
- what can you do
- ?
- I'm lost
- lost
- confused
- frustrated
- what are your capabilities
- help me
- help
- how do I interact with you
- help please
- i'm stuck
- i don't understand
- what can I say
- what can you help me with
- what can you do
- what do i do now
- why doesn't this work
- can you help me

Просмотреть файл

@ -0,0 +1,3 @@
> Reference to other .lu files
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
[All intents](./*)

Просмотреть файл

@ -0,0 +1,21 @@
> None intent and example utterances
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
# None
- spaghetti
- gnocchi
- her cat has no teeth
- world wide pants
- i'd rather be riding my bike
- Cook me something
- Have you any dreams?
- Dont you ever sleep?
- Do you play games?
- Can you fly?
- What's your age?
- Are you old?
- How old are you?
- Getting tired of you
- I am tired of you
- You are boring
- Who is your boss?
- Are you busy?

Просмотреть файл

@ -0,0 +1,46 @@
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "Image",
"url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU",
"size": "stretch"
},
{
"type": "TextBlock",
"spacing": "medium",
"size": "default",
"weight": "bolder",
"text": "Welcome to Bot Framework!",
"wrap": true,
"maxLines": 0
},
{
"type": "TextBlock",
"size": "default",
"isSubtle": "yes",
"text": "Now that you have successfully run your bot, follow the links in this Adaptive Card to expand your knowledge of Bot Framework.",
"wrap": true,
"maxLines": 0
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "Get an overview",
"url": "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"
},
{
"type": "Action.OpenUrl",
"title": "Ask a question",
"url": "https://stackoverflow.com/questions/tagged/botframework"
},
{
"type": "Action.OpenUrl",
"title": "Learn how to deploy",
"url": "https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"
}
]
}

Просмотреть файл

@ -0,0 +1,170 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.BotFramework;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Configuration;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace CELA_Knowledge_Management_Agent
{
/// <summary>
/// The Startup class configures services and the app's request pipeline.
/// </summary>
public class Startup
{
private ILoggerFactory _loggerFactory;
private bool _isProduction = false;
/// <summary>
/// Initializes a new instance of the <see cref="Startup"/> class.
/// This method gets called by the runtime. Use this method to add services to the container.
/// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940.
/// </summary>
/// <param name="env">Provides information about the web hosting environment an application is running in.</param>
/// <seealso cref="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-2.1"/>
public Startup(IHostingEnvironment env)
{
_isProduction = env.IsProduction();
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
/// <summary>
/// Gets the configuration that represents a set of key/value application configuration properties.
/// </summary>
/// <value>
/// The <see cref="IConfiguration"/> that represents a set of key/value application configuration properties.
/// </value>
public IConfiguration Configuration { get; }
/// <summary>
/// This method gets called by the runtime. Use this method to add services to the container.
/// </summary>
/// <param name="services">Specifies the contract for a <see cref="IServiceCollection"/> of service descriptors.</param>
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(sp => Configuration);
var secretKey = Configuration.GetSection("botFileSecret")?.Value;
var botFilePath = Configuration.GetSection("botFilePath")?.Value;
if (!File.Exists(botFilePath))
{
throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}");
}
// Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
BotConfiguration botConfig = null;
try
{
botConfig = BotConfiguration.Load(botFilePath, secretKey);
}
catch
{
var msg = @"Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.
- You can find the botFilePath and botFileSecret in the Azure App Service application settings.
- If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret.
- See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.
";
throw new InvalidOperationException(msg);
}
services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration file could not be loaded. botFilePath: {botFilePath}"));
// Add BotServices singleton.
// Create the connected services from .bot file.
services.AddSingleton(sp => new BotServices(botConfig));
// Retrieve current endpoint.
var environment = _isProduction ? "production" : "development";
var service = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment);
if (service == null && _isProduction)
{
// Attempt to load development environment
service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == "development").FirstOrDefault();
}
if (!(service is EndpointService endpointService))
{
throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
}
// Memory Storage is for local bot debugging only. When the bot
// is restarted, everything stored in memory will be gone.
IStorage dataStore = new MemoryStorage();
// For production bots use the Azure Blob or
// Azure CosmosDB storage providers. For the Azure
// based storage providers, add the Microsoft.Bot.Builder.Azure
// Nuget package to your solution. That package is found at:
// https://www.nuget.org/packages/Microsoft.Bot.Builder.Azure/
// Un-comment the following lines to use Azure Blob Storage
//TODO change bot to use Azure blob and table for storage
// // Storage configuration name or ID from the .bot file.
// const string StorageConfigurationId = "<STORAGE-NAME-OR-ID-FROM-BOT-FILE>";
// var blobConfig = botConfig.FindServiceByNameOrId(StorageConfigurationId);
// if (!(blobConfig is BlobStorageService blobStorageConfig))
// {
// throw new InvalidOperationException($"The .bot file does not contain an blob storage with name '{StorageConfigurationId}'.");
// }
// // Default container name.
// const string DefaultBotContainer = "botstate";
// var storageContainer = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container;
// IStorage dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer);
// Create and add conversation state.
var conversationState = new ConversationState(dataStore);
services.AddSingleton(conversationState);
var userState = new UserState(dataStore);
services.AddSingleton(userState);
services.AddBot<BasicBot>(options =>
{
options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);
options.ChannelProvider = new ConfigurationChannelProvider(Configuration);
// Catches any errors that occur during a conversation turn and logs them to currently
// configured ILogger.
ILogger logger = _loggerFactory.CreateLogger<BasicBot>();
options.OnTurnError = async (context, exception) =>
{
logger.LogError($"Exception caught : {exception}");
await context.SendActivityAsync("Sorry, it looks like something went wrong.");
};
});
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app">Application Builder.</param>
/// <param name="env">Hosting Environment.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> to create logger object for tracing.</param>
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
app.UseDefaultFiles()
.UseStaticFiles()
.UseBotFramework();
}
}
}

Двоичные данные
CELA-Knowledge_Management_Assistant/appsettings.json Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,17 @@
@echo off
setlocal
set DEPLOYMENT_SOURCE=
set DEPLOYMENT_TARGET=%~dp0%.
copy %~dp0wwwroot\default.htm %~dp0app_offline.htm
if exist ..\wwwroot\deploy.cmd (
pushd ..\wwwroot
call deploy.cmd
popd
)
del %~dp0%\app_offline.htm
endlocal

Просмотреть файл

@ -0,0 +1,111 @@
@if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off
:: ----------------------
:: KUDU Deployment Script
:: Version: 1.0.17
:: ----------------------
:: Prerequisites
:: -------------
:: Verify node.js installed
where node 2>nul >nul
IF %ERRORLEVEL% NEQ 0 (
echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment.
goto error
)
:: Setup
:: -----
setlocal enabledelayedexpansion
SET ARTIFACTS=%~dp0%..\artifacts
:: ensure that artifacts exists
IF NOT EXIST "%ARTIFACTS%" (
mkdir "%ARTIFACTS%"
)
IF NOT DEFINED DEPLOYMENT_SOURCE (
SET DEPLOYMENT_SOURCE=%~dp0%.
)
IF NOT DEFINED DEPLOYMENT_TARGET (
SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot
)
IF NOT DEFINED NEXT_MANIFEST_PATH (
SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest
IF NOT DEFINED PREVIOUS_MANIFEST_PATH (
SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest
)
)
IF NOT DEFINED KUDU_SYNC_CMD (
:: Install kudu sync
echo Installing Kudu Sync
call npm install kudusync -g --silent
IF !ERRORLEVEL! NEQ 0 goto error
:: Locally just running "kuduSync" would also work
SET KUDU_SYNC_CMD=%appdata%\npm\kuduSync.cmd
)
IF NOT DEFINED DEPLOYMENT_TEMP (
SET DEPLOYMENT_TEMP=%temp%\___deployTemp%random%
SET CLEAN_LOCAL_DEPLOYMENT_TEMP=true
)
IF DEFINED CLEAN_LOCAL_DEPLOYMENT_TEMP (
IF EXIST "%DEPLOYMENT_TEMP%" rd /s /q "%DEPLOYMENT_TEMP%"
mkdir "%DEPLOYMENT_TEMP%"
)
IF DEFINED MSBUILD_PATH goto MsbuildPathDefined
SET MSBUILD_PATH=%ProgramFiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe
:MsbuildPathDefined
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Deployment
:: ----------
echo Handling ASP.NET Core Web Application deployment.
:: 1. Restore nuget packages
call :ExecuteCmd dotnet restore "BasicBot.sln"
IF !ERRORLEVEL! NEQ 0 goto error
:: 2. Build and publish
call :ExecuteCmd dotnet publish "BasicBot.csproj" --output "%DEPLOYMENT_TEMP%" --configuration Release
IF !ERRORLEVEL! NEQ 0 goto error
:: 3. KuduSync
call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_TEMP%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
IF !ERRORLEVEL! NEQ 0 goto error
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
goto end
:: Execute command routine that will echo out when error
:ExecuteCmd
setlocal
set _CMD_=%*
call %_CMD_%
if "%ERRORLEVEL%" NEQ "0" echo Failed exitCode=%ERRORLEVEL%, command=%_CMD_%
exit /b %ERRORLEVEL%
:error
endlocal
echo An error has occurred during web site deployment.
call :exitSetErrorLevel
call :exitFromFunction 2>nul
:exitSetErrorLevel
exit /b 1
:exitFromFunction
()
:end
endlocal
echo Finished successfully.

Двоичные данные
CELA-Knowledge_Management_Assistant/knowmtest.bot Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,3 @@
nuget restore
msbuild BasicBot.sln -p:DeployOnBuild=true -p:PublishProfile=knowmtest-Web-Deploy.pubxml -p:Password=P4NcGp0JpkhAjemhR9X9fhnzSqZPNpqdFNmFZpamWgrLxS5tNK9ANbYf86rn

Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\CELA-Knowledge_Management_Assistant.dll" stdoutLogEnabled="true" stdoutLogFile="\\?\%home%\LogFiles\stdout" />
</system.webServer>
</configuration>
<!--ProjectGuid: D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8-->

Просмотреть файл

@ -0,0 +1,425 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CELA Knowledge Management Assistant</title>
<style>
body {
margin: 0px;
padding: 0px;
font-family: Segoe UI;
}
html,
body {
height: 100%;
}
header {
background-image: url("data:image/svg+xml,%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 4638.9 651.6' style='enable-background:new 0 0 4638.9 651.6;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%2355A0E0;%7D .st1%7Bfill:none;%7D .st2%7Bfill:%230058A8;%7D .st3%7Bfill:%23328BD8;%7D .st4%7Bfill:%23B6DCF1;%7D .st5%7Bopacity:0.2;fill:url(%23SVGID_1_);enable-background:new ;%7D%0A%3C/style%3E%3Crect y='1.1' class='st0' width='4640' height='646.3'/%3E%3Cpath class='st1' d='M3987.8,323.6L4310.3,1.1h-65.6l-460.1,460.1c-17.5,17.5-46.1,17.5-63.6,0L3260.9,1.1H0v646.3h3660.3 L3889,418.7c17.5-17.5,46.1-17.5,63.6,0l228.7,228.7h66.6l-260.2-260.2C3970.3,369.8,3970.3,341.1,3987.8,323.6z'/%3E%3Cpath class='st2' d='M3784.6,461.2L4244.7,1.1h-983.9l460.1,460.1C3738.4,478.7,3767.1,478.7,3784.6,461.2z'/%3E%3Cpath class='st3' d='M4640,1.1h-329.8l-322.5,322.5c-17.5,17.5-17.5,46.1,0,63.6l260.2,260.2H4640L4640,1.1L4640,1.1z'/%3E%3Cpath class='st4' d='M3889,418.8l-228.7,228.7h521.1l-228.7-228.7C3935.2,401.3,3906.5,401.3,3889,418.8z'/%3E%3ClinearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='3713.7576' y1='438.1175' x2='3911.4084' y2='14.2535' gradientTransform='matrix(1 0 0 -1 0 641.3969)'%3E%3Cstop offset='0' style='stop-color:%23FFFFFF;stop-opacity:0.5'/%3E%3Cstop offset='1' style='stop-color:%23FFFFFF'/%3E%3C/linearGradient%3E%3Cpath class='st5' d='M3952.7,124.5c-17.5-17.5-46.1-17.5-63.6,0l-523,523h1109.6L3952.7,124.5z'/%3E%3C/svg%3E%0A");
background-repeat: no-repeat;
background-size: 100%;
background-position: right;
background-color: #55A0E0;
width: 100%;
font-size: 44px;
height: 120px;
color: white;
padding: 30px 0 40px 0px;
display: inline-block;
}
.header-icon {
background-image: url("data:image/svg+xml;utf8,%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%20x%3D%220px%22%20y%3D%220px%22%0A%09%20viewBox%3D%220%200%20150.2%20125%22%20style%3D%22enable-background%3Anew%200%200%20150.2%20125%3B%22%20xml%3Aspace%3D%22preserve%22%3E%0A%3Cstyle%20type%3D%22text/css%22%3E%0A%09.st0%7Bfill%3Anone%3B%7D%0A%09.st1%7Bfill%3A%23FFFFFF%3B%7D%0A%3C/style%3E%0A%3Crect%20x%3D%220.5%22%20class%3D%22st0%22%20width%3D%22149.7%22%20height%3D%22125%22/%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M59%2C102.9L21.8%2C66c-3.5-3.5-3.5-9.1%2C0-12.5l37-36.5l2.9%2C3l-37%2C36.4c-1.8%2C1.8-1.8%2C4.7%2C0%2C6.6l37.2%2C37L59%2C102.9z%22%0A%09%09/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M92.5%2C102.9l-3-3l37.2-37c0.9-0.9%2C1.4-2%2C1.4-3.3c0-1.2-0.5-2.4-1.4-3.3L89.5%2C20l2.9-3l37.2%2C36.4%0A%09%09c1.7%2C1.7%2C2.6%2C3.9%2C2.6%2C6.3s-0.9%2C4.6-2.6%2C6.3L92.5%2C102.9z%22/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M90.1%2C68.4c-4.5%2C0-8-3.5-8-8.1c0-4.5%2C3.5-8.1%2C8-8.1c4.4%2C0%2C8%2C3.7%2C8%2C8.1C98.1%2C64.7%2C94.4%2C68.4%2C90.1%2C68.4z%0A%09%09%20M90.1%2C56.5c-2.2%2C0-3.8%2C1.7-3.8%2C3.9c0%2C2.2%2C1.7%2C3.9%2C3.8%2C3.9c1.9%2C0%2C3.8-1.6%2C3.8-3.9S91.9%2C56.5%2C90.1%2C56.5z%22/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M61.4%2C68.4c-4.5%2C0-8-3.5-8-8.1c0-4.5%2C3.5-8.1%2C8-8.1c4.4%2C0%2C8%2C3.7%2C8%2C8.1C69.5%2C64.7%2C65.8%2C68.4%2C61.4%2C68.4z%0A%09%09%20M61.4%2C56.5c-2.2%2C0-3.8%2C1.7-3.8%2C3.9c0%2C2.2%2C1.7%2C3.9%2C3.8%2C3.9c1.9%2C0%2C3.8-1.6%2C3.8-3.9S63.3%2C56.5%2C61.4%2C56.5z%22/%3E%0A%3C/g%3E%0A%3C/svg%3E%0A");
background-repeat: no-repeat;
float: left;
height: 140px;
width: 140px;
display: inline-block;
vertical-align: middle;
}
.header-text {
padding-left: 1%;
color: #FFFFFF;
font-family: "Segoe UI";
font-size: 72px;
font-weight: 300;
letter-spacing: 0.35px;
line-height: 96px;
display: inline-block;
vertical-align: middle;
}
.header-inner-container {
min-width: 480px;
max-width: 1366px;
margin-left: auto;
margin-right: auto;
vertical-align: middle;
}
.header-inner-container::after {
content: "";
clear: both;
display: table;
}
.main-content-area {
padding-left: 30px;
}
.content-title {
color: #000000;
font-family: "Segoe UI";
font-size: 46px;
font-weight: 300;
line-height: 62px;
}
.main-text {
color: #808080;
font-size: 24px;
font-family: "Segoe UI";
font-size: 24px;
font-weight: 200;
line-height: 32px;
}
.main-text-p1 {
padding-top: 48px;
padding-bottom: 28px;
}
.endpoint {
height: 32px;
width: 571px;
color: #808080;
font-family: "Segoe UI";
font-size: 24px;
font-weight: 200;
line-height: 32px;
padding-top: 28px;
}
.how-to-build-section {
padding-top: 20px;
padding-left: 30px;
}
.how-to-build-section > h3 {
font-size: 16px;
font-weight: 600;
letter-spacing: 0.35px;
line-height: 22px;
margin: 0 0 24px 0;
text-transform: uppercase;
}
.step-container {
display: flex;
align-items: stretch;
position: relative;
}
.step-container dl {
border-left: 1px solid #A0A0A0;
display: block;
padding: 0 24px;
margin: 0;
}
.step-container dl > dt::before {
background-color: white;
border: 1px solid #A0A0A0;
border-radius: 100%;
content: '';
left: 47px;
height: 11px;
position: absolute;
width: 11px;
}
.step-container dl > .test-bullet::before {
background-color: blue;
}
.step-container dl > dt {
display: block;
font-size: inherit;
font-weight: bold;
line-height: 20px;
}
.step-container dl > dd {
font-size: inherit;
line-height: 20px;
margin-left: 0;
padding-bottom: 32px;
}
.step-container:last-child dl {
border-left: 1px solid transparent;
}
.ctaLink {
background-color: transparent;
border: 1px solid transparent;
color: #006AB1;
cursor: pointer;
font-weight: 600;
padding: 0;
white-space: normal;
}
.ctaLink:focus {
outline: 1px solid #00bcf2;
}
.ctaLink:hover {
text-decoration: underline;
}
.step-icon {
display: flex;
height: 38px;
margin-right: 15px;
width: 38px;
}
.step-icon > div {
height: 30px;
width: 30px;
background-repeat: no-repeat;
}
.ms-logo-container {
min-width: 580px;
max-width: 980px;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
transition: bottom 400ms;
}
.ms-logo {
float: right;
background-image: url("data:image/svg+xml;utf8,%0A%3Csvg%20version%3D%221.1%22%20id%3D%22MS-symbol%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%20x%3D%220px%22%20y%3D%220px%22%0A%09%20viewBox%3D%220%200%20400%20120%22%20style%3D%22enable-background%3Anew%200%200%20400%20120%3B%22%20xml%3Aspace%3D%22preserve%22%3E%0A%3Cstyle%20type%3D%22text/css%22%3E%0A%09.st0%7Bfill%3Anone%3B%7D%0A%09.st1%7Bfill%3A%23737474%3B%7D%0A%09.st2%7Bfill%3A%23D63F26%3B%7D%0A%09.st3%7Bfill%3A%23167D3E%3B%7D%0A%09.st4%7Bfill%3A%232E76BC%3B%7D%0A%09.st5%7Bfill%3A%23FDB813%3B%7D%0A%3C/style%3E%0A%3Crect%20x%3D%220.6%22%20class%3D%22st0%22%20width%3D%22398.7%22%20height%3D%22119%22/%3E%0A%3Cpath%20class%3D%22st1%22%20d%3D%22M171.3%2C38.4v43.2h-7.5V47.7h-0.1l-13.4%2C33.9h-5l-13.7-33.9h-0.1v33.9h-6.9V38.4h10.8l12.4%2C32h0.2l13.1-32H171.3%0A%09z%20M177.6%2C41.7c0-1.2%2C0.4-2.2%2C1.3-3c0.9-0.8%2C1.9-1.2%2C3.1-1.2c1.3%2C0%2C2.4%2C0.4%2C3.2%2C1.3c0.8%2C0.8%2C1.3%2C1.8%2C1.3%2C3c0%2C1.2-0.4%2C2.2-1.3%2C3%0A%09c-0.9%2C0.8-1.9%2C1.2-3.2%2C1.2s-2.3-0.4-3.1-1.2C178%2C43.8%2C177.6%2C42.8%2C177.6%2C41.7z%20M185.7%2C50.6v31h-7.3v-31H185.7z%20M207.8%2C76.3%0A%09c1.1%2C0%2C2.3-0.3%2C3.6-0.8c1.3-0.5%2C2.5-1.2%2C3.6-2v6.8c-1.2%2C0.7-2.5%2C1.2-4%2C1.5c-1.5%2C0.3-3.1%2C0.5-4.9%2C0.5c-4.6%2C0-8.3-1.4-11.1-4.3%0A%09c-2.9-2.9-4.3-6.6-4.3-11c0-5%2C1.5-9.1%2C4.4-12.3c2.9-3.2%2C7-4.8%2C12.4-4.8c1.4%2C0%2C2.7%2C0.2%2C4.1%2C0.5c1.4%2C0.4%2C2.5%2C0.8%2C3.3%2C1.2v7%0A%09c-1.1-0.8-2.3-1.5-3.4-1.9c-1.2-0.5-2.4-0.7-3.6-0.7c-2.9%2C0-5.2%2C0.9-7%2C2.8c-1.8%2C1.9-2.7%2C4.4-2.7%2C7.6c0%2C3.1%2C0.8%2C5.6%2C2.5%2C7.3%0A%09C202.6%2C75.4%2C204.9%2C76.3%2C207.8%2C76.3z%20M235.7%2C50.1c0.6%2C0%2C1.1%2C0%2C1.6%2C0.1s0.9%2C0.2%2C1.2%2C0.3v7.4c-0.4-0.3-0.9-0.5-1.7-0.8%0A%09c-0.7-0.3-1.6-0.4-2.7-0.4c-1.8%2C0-3.3%2C0.8-4.5%2C2.3c-1.2%2C1.5-1.9%2C3.8-1.9%2C7v15.6h-7.3v-31h7.3v4.9h0.1c0.7-1.7%2C1.7-3%2C3-4%0A%09C232.2%2C50.6%2C233.8%2C50.1%2C235.7%2C50.1z%20M238.9%2C66.6c0-5.1%2C1.4-9.2%2C4.3-12.2c2.9-3%2C6.9-4.5%2C12.1-4.5c4.8%2C0%2C8.6%2C1.4%2C11.3%2C4.3%0A%09c2.7%2C2.9%2C4.1%2C6.8%2C4.1%2C11.7c0%2C5-1.4%2C9-4.3%2C12c-2.9%2C3-6.8%2C4.5-11.8%2C4.5c-4.8%2C0-8.6-1.4-11.4-4.2C240.3%2C75.3%2C238.9%2C71.4%2C238.9%2C66.6z%0A%09%20M246.5%2C66.3c0%2C3.2%2C0.7%2C5.7%2C2.2%2C7.4c1.5%2C1.7%2C3.6%2C2.6%2C6.3%2C2.6c2.7%2C0%2C4.7-0.9%2C6.1-2.6c1.4-1.7%2C2.1-4.2%2C2.1-7.6c0-3.3-0.7-5.8-2.2-7.5%0A%09c-1.4-1.7-3.4-2.5-6-2.5c-2.7%2C0-4.7%2C0.9-6.2%2C2.7C247.2%2C60.5%2C246.5%2C63%2C246.5%2C66.3z%20M281.5%2C58.8c0%2C1%2C0.3%2C1.9%2C1%2C2.5%0A%09c0.7%2C0.6%2C2.1%2C1.3%2C4.4%2C2.2c2.9%2C1.2%2C5%2C2.5%2C6.1%2C3.9c1.2%2C1.5%2C1.8%2C3.2%2C1.8%2C5.3c0%2C2.9-1.1%2C5.3-3.4%2C7c-2.2%2C1.8-5.3%2C2.7-9.1%2C2.7%0A%09c-1.3%2C0-2.7-0.2-4.3-0.5c-1.6-0.3-2.9-0.7-4-1.2v-7.2c1.3%2C0.9%2C2.8%2C1.7%2C4.3%2C2.2c1.5%2C0.5%2C2.9%2C0.8%2C4.2%2C0.8c1.6%2C0%2C2.9-0.2%2C3.6-0.7%0A%09c0.8-0.5%2C1.2-1.2%2C1.2-2.3c0-1-0.4-1.9-1.2-2.5c-0.8-0.7-2.4-1.5-4.6-2.4c-2.7-1.1-4.6-2.4-5.7-3.8c-1.1-1.4-1.7-3.2-1.7-5.4%0A%09c0-2.8%2C1.1-5.1%2C3.3-6.9c2.2-1.8%2C5.1-2.7%2C8.6-2.7c1.1%2C0%2C2.3%2C0.1%2C3.6%2C0.4c1.3%2C0.2%2C2.5%2C0.6%2C3.4%2C0.9v6.9c-1-0.6-2.1-1.2-3.4-1.7%0A%09c-1.3-0.5-2.6-0.7-3.8-0.7c-1.4%2C0-2.5%2C0.3-3.2%2C0.8C281.9%2C57.1%2C281.5%2C57.8%2C281.5%2C58.8z%20M297.9%2C66.6c0-5.1%2C1.4-9.2%2C4.3-12.2%0A%09c2.9-3%2C6.9-4.5%2C12.1-4.5c4.8%2C0%2C8.6%2C1.4%2C11.3%2C4.3c2.7%2C2.9%2C4.1%2C6.8%2C4.1%2C11.7c0%2C5-1.4%2C9-4.3%2C12c-2.9%2C3-6.8%2C4.5-11.8%2C4.5%0A%09c-4.8%2C0-8.6-1.4-11.4-4.2C299.4%2C75.3%2C297.9%2C71.4%2C297.9%2C66.6z%20M305.5%2C66.3c0%2C3.2%2C0.7%2C5.7%2C2.2%2C7.4c1.5%2C1.7%2C3.6%2C2.6%2C6.3%2C2.6%0A%09c2.7%2C0%2C4.7-0.9%2C6.1-2.6c1.4-1.7%2C2.1-4.2%2C2.1-7.6c0-3.3-0.7-5.8-2.2-7.5c-1.4-1.7-3.4-2.5-6-2.5c-2.7%2C0-4.7%2C0.9-6.2%2C2.7%0A%09C306.3%2C60.5%2C305.5%2C63%2C305.5%2C66.3z%20M353.9%2C56.6h-10.9v25h-7.4v-25h-5.2v-6h5.2v-4.3c0-3.3%2C1.1-5.9%2C3.2-8c2.1-2.1%2C4.8-3.1%2C8.1-3.1%0A%09c0.9%2C0%2C1.7%2C0%2C2.4%2C0.1c0.7%2C0.1%2C1.3%2C0.2%2C1.8%2C0.4V42c-0.2-0.1-0.7-0.3-1.3-0.5c-0.6-0.2-1.3-0.3-2.1-0.3c-1.5%2C0-2.7%2C0.5-3.5%2C1.4%0A%09s-1.2%2C2.4-1.2%2C4.2v3.7h10.9v-7l7.3-2.2v9.2h7.4v6h-7.4v14.5c0%2C1.9%2C0.3%2C3.3%2C1%2C4c0.7%2C0.8%2C1.8%2C1.2%2C3.3%2C1.2c0.4%2C0%2C0.9-0.1%2C1.5-0.3%0A%09c0.6-0.2%2C1.1-0.4%2C1.6-0.7v6c-0.5%2C0.3-1.2%2C0.5-2.3%2C0.7c-1.1%2C0.2-2.1%2C0.3-3.2%2C0.3c-3.1%2C0-5.4-0.8-6.9-2.5c-1.5-1.6-2.3-4.1-2.3-7.4%0A%09V56.6z%22/%3E%0A%3Cg%3E%0A%09%3Crect%20x%3D%2231%22%20y%3D%2224%22%20class%3D%22st2%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2268.8%22%20y%3D%2224%22%20class%3D%22st3%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2231%22%20y%3D%2261.8%22%20class%3D%22st4%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2268.8%22%20y%3D%2261.8%22%20class%3D%22st5%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%3C/g%3E%0A%3C/svg%3E%0A");
}
.ms-logo-container > div {
min-height: 60px;
width: 150px;
background-repeat: no-repeat;
}
.row {
padding: 90px 0px 0 20px;
min-width: 480px;
max-width: 1366px;
margin-left: auto;
margin-right: auto;
}
.column {
float: left;
width: 45%;
padding-right: 20px;
}
.row:after {
content: "";
display: table;
clear: both;
}
a {
text-decoration: none;
}
.download-the-emulator {
height: 20px;
color: #0063B1;
font-size: 15px;
line-height: 20px;
padding-bottom: 70px;
}
.how-to-iframe {
max-width: 700px !important;
min-width: 650px !important;
height: 700px !important;
}
.remove-frame-height {
height: 10px;
}
@media only screen and (max-width: 1300px) {
.ms-logo {
padding-top: 30px;
}
.header-text {
font-size: 40x;
}
.column {
float: none;
padding-top: 30px;
width: 100%;
}
.ms-logo-container {
padding-top: 30px;
min-width: 480px;
max-width: 650px;
margin-left: auto;
margin-right: auto;
}
.row {
padding: 20px 0px 0 20px;
min-width: 480px;
max-width: 650px;
margin-left: auto;
margin-right: auto;
}
}
@media only screen and (max-width: 1370px) {
header {
background-color: #55A0E0;
background-size: auto 200px;
}
}
@media only screen and (max-width: 1230px) {
header {
background-color: #55A0E0;
background-size: auto 200px;
}
.header-text {
font-size: 44px;
}
.header-icon {
height: 120px;
width: 120px;
}
}
@media only screen and (max-width: 1000px) {
header {
background-color: #55A0E0;
background-image: none;
}
}
@media only screen and (max-width: 632px) {
.header-text {
font-size: 32px;
}
.row {
padding: 10px 0px 0 10px;
max-width: 490px !important;
min-width: 410px !important;
}
.endpoint {
font-size: 25px;
}
.main-text {
font-size: 20px;
}
.step-container dl > dd {
font-size: 14px;
}
.column {
padding-right: 5px;
}
.header-icon {
height: 110px;
width: 110px;
}
.how-to-iframe {
max-width: 480px !important;
min-width: 400px !important;
height: 650px !important;
overflow: hidden;
}
}
.remove-frame-height {
max-height: 10px;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
loadFrame();
});
var loadFrame = function () {
var iframe = document.createElement('iframe');
iframe.setAttribute("id", "iframe");
var offLineHTMLContent = "";
var frameElement = document.getElementById("how-to-iframe");
if (window.navigator.onLine) {
iframe.src = 'https://docs.botframework.com/static/abs/pages/f5.htm';
iframe.setAttribute("scrolling", "no");
iframe.setAttribute("frameborder", "0");
iframe.setAttribute("width", "100%");
iframe.setAttribute("height", "100%");
var frameDiv = document.getElementById("how-to-iframe");
frameDiv.appendChild(iframe);
} else {
frameElement.classList.add("remove-frame-height");
}
};
</script>
</head>
<body>
<header class="header">
<div class="header-inner-container">
<div class="header-icon" style="display: inline-block"></div>
<div class="header-text" style="display: inline-block">CELA KM Assistant</div>
</div>
</header>
<div class="row">
<div class="column" class="main-content-area">
<iframe src='https://webchat.botframework.com/embed/knowmtest?s=[ENTER_KEY_HERE]' style='min-width: 400px; width: 100%; min-height: 500px;'></iframe>
</div>
<div class="column" class="main-content-area">
<div class="content-title">How this Assistant works</div>
<div class="main-text">
-Create and send an email decorated with text tags (e.g., #MID-Testing and #Privacy). Include <a href="mailto:[UPDATE-THIS]@microsoft.com">[UPDATE-THIS]@microsoft.com</a> as a recipient.
</div>
<div class="main-text">
-A <a href="https://flow.microsoft.com/en-us/">Microsoft Flow</a> triggers a workflow that sends the email contents to <a href="https://azure.microsoft.com/">Microsoft Azure</a>. Azure parses the email and hands data back to Flow that instructs Flow to store attached documents to <a href="https://products.office.com/en-us/sharepoint/collaboration">Microsoft SharePoint</a>.
</div>
<div class="main-text">
-An <a href="https://azure.microsoft.com/en-us/services/app-service/web/">Azure Web App</a> deployed web service breaks the email into entities and stores them in <a href="https://docs.microsoft.com/en-us/azure/cosmos-db/introduction">Cosmos Graph Database</a>.
</div>
<div class="main-text">
-An <a href="https://azure.microsoft.com/en-us/services/bot-service/">Azure Bot Service</a> calls the <a href="https://www.luis.ai/">Azure Language Understanding Cognitive Service</a> to translate natural language requests into graph queries that answer questions.
</div>
</div>
</div>
<div class="ms-logo-container">
<div class="ms-logo"></div>
<div>Copyright Microsoft</div>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,15 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CELA_Knowledge_Management_Data_Services.tests.BusinessLogic
{
[TestClass()]
public class CommunicationProcessingBusinessLogicTests
{
}
}

Просмотреть файл

@ -0,0 +1,26 @@
using CELA_Knowledge_Management_Data_Services.BusinessLogic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CELA_Knowledge_Management_Data_Services.tests.BusinessLogic
{
[TestClass()]
class GraphQueryBusinessLogicTests
{
[TestMethod]
public void ConformStringForQueryTest()
{
var stringTest = "Some string that has an invalid character like $";
var result = GraphQueryBusinessLogic.ConformStringForQuery(stringTest);
if (result.Length >= stringTest.Length)
{
Assert.Fail("Failed to remove disallowed character.");
}
}
}
}

Просмотреть файл

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C58D9225-E2A2-417C-8745-D78A091BAB72}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CELA_Knowledge_Management_Data_Services.tests</RootNamespace>
<AssemblyName>CELA-Knowledge_Management_Data_Services.tests</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Gremlin.Net, Version=3.4.0.0, Culture=neutral, PublicKeyToken=d2035e9aa387a711, processorArchitecture=MSIL">
<HintPath>..\packages\Gremlin.Net.3.4.0\lib\netstandard2.0\Gremlin.Net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Azure.KeyVault.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Storage, Version=9.3.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\WindowsAzure.Storage.9.3.3\lib\net45\Microsoft.WindowsAzure.Storage.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
</ItemGroup>
<ItemGroup>
<Compile Include="BusinessLogic\CommunicationProcessingBusinessLogicTests.cs" />
<Compile Include="BusinessLogic\GraphQueryBusinessLogicTests.cs" />
<Compile Include="KnowledgeManagementDataServicesTestSettings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="GraphTransactionTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CELA-Knowledge_Management_Data_Services\CELA-Knowledge_Management_Data_Services.csproj">
<Project>{6d8bc8a4-9750-4560-a544-7e53cd47948d}</Project>
<Name>CELA-Knowledge_Management_Data_Services</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" />
</Project>

Двоичный файл не отображается.

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("CELA-Knowledge_Management_Data_Services.tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CELA-Knowledge_Management_Data_Services.tests")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("c58d9225-e2a2-417c-8745-d78a091bab72")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Gremlin.Net" version="3.4.0" targetFramework="net461" />
<package id="Microsoft.Azure.KeyVault.Core" version="1.0.0" targetFramework="net461" />
<package id="Microsoft.CSharp" version="4.3.0" targetFramework="net461" />
<package id="MSTest.TestAdapter" version="1.3.2" targetFramework="net461" />
<package id="MSTest.TestFramework" version="1.3.2" targetFramework="net461" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
<package id="WindowsAzure.Storage" version="9.3.3" targetFramework="net461" />
</packages>

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,890 @@
using CELA_Knowledge_Management_Data_Services.DataUtilities;
using CELA_Knowledge_Management_Data_Services.Models;
using Gremlin.Net.Driver;
using Gremlin.Net.Driver.Exceptions;
using Gremlin.Net.Structure.IO.GraphSON;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CELA_Knowledge_Management_Data_Services.BusinessLogic
{
public class CommunicationProcessingBusinessLogic
{
public const string CommunicationAddressDelimiter = ";";
public const string KeyBinder = ")!(@*#&$^%";
public const string DefaultGraphPartition = "CELA";
public const string GraphPartitionKeyProperty = "partitionKey";
public const int MaximumTagLength = 64;
public const string TagDelimiter = " ";
// General Vertex Properties
public const string VertexIDProperty = "id";
public const string VertexNameProperty = "name";
//Communicator
public const string CommunicatorVertexLabel = "communicator";
public const string CommunicatorVertexFullnameProperty = "full name";
public const string CommunicatorVertexEmailAliasProperty = "alias";
// Organization
public const string OrganizationVertexLabel = "organization";
public const string OrganizationVertexFullnameProperty = "full name";
// Communication
public const string CommunicationVertexLabel = "communication";
public const string CommunicationVertexPartitionKeyProperty = "partition key";
public const string CommunicationVertexRowKeyProperty = "row key";
public const string CommunicationVertexSubjectProperty = "subject";
public const string CommunicationVertexUTCTimeProperty = "UTC time";
public const string CommunicationVertexYearProperty = "year";
public const string CommunicationVertexMonthProperty = "month";
public const string CommunicationVertexDayProperty = "day";
public const string CommunicationVertexConversationIDProperty = "conversation id";
public const string CommunicationVertexReferenceKey = "reference key";
// Tag
public const string TagVertexLabel = "tag";
public const string TagVertexTypeProperty = "type";
public const string TagVertexKeyProperty = "key";
// Topic
public const string TopicVertexLabel = "topic";
public const string TopicVertexDescriptionProperty = "description";
public const string TopicVertexTypeProperty = "type";
public const string TopicVertexKeyProperty = "key";
// Project
public const string ProjectVertexLabel = "project";
public const string ProjectVertexTypeProperty = "type";
// Document
public const string DocumentVertexLabel = "document";
public const string DocumentVertexNameProperty = "name";
public const string DocumentVertexTypeProperty = "type";
public const string DocumentVertexLibraryProperty = "library";
public const string DocumentVertexPathProperty = "path";
public const string DocumentVertexExternalKeyProperty = "key";
// Matter
public const string MatterVertexLabel = "matter";
// Communicator->Organization
public const string CommunicatorOrganizationEdgeLabel = "member of";
// Communicator->Communication
public const string CommunicatorCommunicationEdgeLabel = "sends";
// Communication->Tag
public const string CommunicationTagEdgeLabel = "relates to";
// Communication->Document
public const string CommunicationDocumentEdgeLabel = "relates to";
// Tag->Tag
public const string TagTagEdgeLabel = "used with";
// Communication->Communicator
public const string CommunicationCommunicatorEdgeLabel = "receives";
public const string CommunicationCommunicatorPrimaryRecipientEdgeProperty = "primary recipient";
public const string CommunicationCommunicatorSecondaryRecipientEdgeProperty = "secondary recipient";
// Tag->Project
public const string TagProjectEdgeLabel = "used by";
public const string TagProjectUsageProperty = "relates to";
// Communication->Matter
public const string CommunicationMatterEdgeLabel = "relates to";
// Tag->Matter
public const string TagMatterEdgeLabel = "relates to";
// Document->Matter
public const string DocumentMatterEdgeLabel = "relates to";
public CommunicationProcessingBusinessLogic()
{
}
public static GremlinServer CreateGremlinServer(string Hostname, int Port, string AuthKey, string Database, string Collection)
{
return new GremlinServer(Hostname, Port, enableSsl: true,
username: "/dbs/" + Database + "/colls/" + Collection,
password: AuthKey);
}
public static GremlinClient CreateGremlinClient(string Hostname, int Port, string AuthKey, string Database, string Collection)
{
return new GremlinClient(CreateGremlinServer(Hostname, Port, AuthKey, Database, Collection), new GraphSON2Reader(), new GraphSON2Writer(), GremlinClient.GraphSON2MimeType);
}
public static GremlinClient CreateGremlinClient(IGraphConfiguration graphConfiguration)
{
return CreateGremlinClient(graphConfiguration.GetGraphDatabaseHostname(), graphConfiguration.GetGraphDatabasePort(), graphConfiguration.GetGraphDatabaseAccessKey(), graphConfiguration.GetGraphDatabaseName(), graphConfiguration.GetGraphDatabaseCollectionName());
}
public static string ProcessDocumentToGraphDB(Document Attachment, string Hostname, int Port, string AuthKey, string Database, string Collection)
{
// Make sure we have a reference key to look up the associated email
if (!string.IsNullOrEmpty(Attachment.referenceKey))
{
using (var gremlinClient = CreateGremlinClient(Hostname, Port, AuthKey, Database, Collection))
{
// Find the communication based on the reference key
var results = GetGraphVertex(gremlinClient, CommunicationVertexLabel, CommunicationVertexReferenceKey, Attachment.referenceKey);
// If the communication was found
if (results.Count == 1)
{
var output = (JArray)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(results));
string communicationID = string.Empty;
foreach (var item in output)
{
communicationID = item[VertexIDProperty].Value<string>();
if (!string.IsNullOrEmpty(communicationID))
{
break;
}
}
// Pull the id property and return that if found.
// var communicationID = output[VertexIDProperty].Value<string>();
// Create the attachment
Dictionary<string, string> properties = new Dictionary<string, string>();
if (string.IsNullOrEmpty(Attachment.type) && !string.IsNullOrEmpty(Attachment.name))
{
if (Attachment.name.IndexOf(".") > -1)
{
var attachmentType = Attachment.name.Substring(Attachment.name.LastIndexOf("."));
properties.Add(DocumentVertexTypeProperty, attachmentType);
}
}
else
{
properties.Add(DocumentVertexTypeProperty, Attachment.type);
}
properties.Add(DocumentVertexLibraryProperty, Attachment.sharepointlibrary);
properties.Add(DocumentVertexPathProperty, Attachment.sharepointlibrarypath);
properties.Add(DocumentVertexExternalKeyProperty, Attachment.referenceKey);
var attachmentID = AddGraphVertex(gremlinClient, DocumentVertexLabel, Attachment.name, properties, Attachment.id);
//Create the edge between the communication and the attachment
var communicatorCommunicationEdgeQueryResult = AddGraphEdge(gremlinClient, communicationID, attachmentID, CommunicationDocumentEdgeLabel);
if (!string.IsNullOrEmpty(Attachment.matter))
{
//Insert or retrieve the ID for the matter
var matterID = AddGraphVertex(gremlinClient, MatterVertexLabel, Attachment.matter);
//Add an edge from the document to the matter
var documentMatterEdgeQueryResults = AddGraphEdge(gremlinClient, attachmentID, matterID, DocumentMatterEdgeLabel);
}
return attachmentID;
}
}
}
return string.Empty;
}
public static bool ProcessCommunicationToGraphDB(EmailSearch Communication, string Hostname, int Port, string AuthKey, string Database, string Collection)
{
using (var gremlinClient = CreateGremlinClient(Hostname, Port, AuthKey, Database, Collection))
{
//Add the communication sender
var communicatorID = AddCommunicatorAndOrganization(Communication.EmailSender, gremlinClient);
//Add the communication with properties
var communicationID = AddCommunication(Communication, gremlinClient);
//Add an edge from the communicator to the communcation
var communicatorCommunicationEdgeQueryResult = AddGraphEdge(gremlinClient, communicatorID, communicationID, CommunicatorCommunicationEdgeLabel);
//Add the communication secondary recipients with edges, note that we put this first to ensure primary relationship overwrite if applicable
var secondaryRecipientIDs = ProcessCommunicationRecipients(gremlinClient, communicationID, Communication.EmailCcRecipients, CommunicationCommunicatorSecondaryRecipientEdgeProperty);
//Add the communication primary recipients with edges
var primaryRecipientIDs = ProcessCommunicationRecipients(gremlinClient, communicationID, Communication.EmailToRecipients, CommunicationCommunicatorPrimaryRecipientEdgeProperty);
string matterID = string.Empty;
if (!string.IsNullOrEmpty(Communication.MatterId))
{
//Add the matter
matterID = AddGraphVertex(gremlinClient, MatterVertexLabel, Communication.MatterId);
//Add an edge from the communication to the matter
var communicationMatterEdgeQueryResult = AddGraphEdge(gremlinClient, communicationID, matterID, CommunicationMatterEdgeLabel);
}
//Add the tags and edges
List<string> tagIDs = null;
if (Communication.EmailTagCluster != null && Communication.EmailTagCluster.Length > 0)
{
List<string> tags = CommunicationProcessingBusinessLogic.ParseConcatenatedString(Communication.EmailTagCluster, TagDelimiter);
tagIDs = new List<string>();
foreach (var tag in tags)
{
tagIDs.Add(AddGraphVertex(gremlinClient, TagVertexLabel, tag));
// Rethinking this//if there is a matter associated with this communication ensure the tag and the matter are connected
//if (!string.IsNullOrEmpty(matterID) && string.Equals(matterID, tag, StringComparison.OrdinalIgnoreCase)
//{
//}
}
foreach (var tagID in tagIDs)
{
//Add an edge from the communication to the tags
var communicationTagEdgeQueryResult = AddGraphEdge(gremlinClient, communicationID, tagID, CommunicationTagEdgeLabel);
if (!string.IsNullOrEmpty(matterID))
{
var queryResults = GetGraphEdge(gremlinClient, tagID, matterID, TagMatterEdgeLabel);
//If we have no edge, add it
if (queryResults.Count == 0)
{
//Add an edge from the tags to the matter
var tagMatterEdgeQueryResults = AddGraphEdge(gremlinClient, tagID, matterID, TagMatterEdgeLabel);
}
}
}
}
}
return true;
}
private static List<string> ProcessCommunicationRecipients(GremlinClient gremlinClient, string communicationID, string CommunicationRecipients, string RecipientEdgePropertyName)
{
List<string> recipients = null;
if (CommunicationRecipients != null && CommunicationRecipients.Length > 0)
{
recipients = new List<string>();
//Process the vertices
foreach (var recipient in ParseConcatenatedString(CommunicationRecipients))
{
var receipientID = AddCommunicatorAndOrganization(recipient, gremlinClient);
recipients.Add(receipientID);
}
//Process the edges
foreach (var recipientID in recipients)
{
Dictionary<string, string> queryProperties = new Dictionary<string, string>();
queryProperties.Add(RecipientEdgePropertyName, "true");
var communicationCommunicatorEdgeQueryResult = AddGraphEdge(gremlinClient, communicationID, recipientID, CommunicationCommunicatorEdgeLabel, queryProperties);
}
}
return recipients;
}
public static string GetGraphVertexID()
{
return Guid.NewGuid().ToString();
}
public static ResultSet<dynamic> GetGraphVertex(GremlinClient GremlinClient, string VertexLabel, string PropertyName, string PropertyValue)
{
try
{
var query = GraphQueryBusinessLogic.CreateRetrieveVertexGraphQuery(VertexLabel, PropertyName, PropertyValue);
var results = TransactGraphQuery(GremlinClient, query);
return results;
}
catch (Exception)
{
throw;
}
}
public static string AddGraphVertex(GremlinClient GremlinClient, string VertexType, string VertexName = null, Dictionary<string, string> Properties = null, string id = null)
{
try
{
if (string.IsNullOrEmpty(id))
{
id = GetGraphVertexID();
}
if (VertexName == null)
{
VertexName = id;
}
var results = TransactGraphQuery(GremlinClient, GraphQueryBusinessLogic.CreateVertexIfDoesNotExistGraphQuery(VertexType, VertexName, id, Properties));
foreach (var result in results)
{
// The vertex results are formed as Dictionaries with a nested dictionary for their properties
var output = (JObject)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(result));
// Pull the id property and return that if found.
id = output[VertexIDProperty].Value<string>();
}
return id;
}
catch (Exception)
{
throw;
}
}
public static ResultSet<dynamic> UpdateGraphEdge(GremlinClient GremlinClient, string FromVertexID, string ToVertexID, string EdgeLabel, Dictionary<string, string> Properties)
{
try
{
var query = GraphQueryBusinessLogic.CreateUpdateEdgeGraphQuery(FromVertexID, ToVertexID, EdgeLabel, Properties);
var results = TransactGraphQuery(GremlinClient, query);
return results;
}
catch (Exception)
{
throw;
}
}
public static ResultSet<dynamic> GetGraphEdge(GremlinClient GremlinClient, string FromVertexID, string ToVertexID, string EdgeLabel)
{
try
{
var query = GraphQueryBusinessLogic.CreateRetrieveEdgeGraphQuery(FromVertexID, ToVertexID, EdgeLabel);
var results = TransactGraphQuery(GremlinClient, query);
return results;
}
catch (Exception)
{
throw;
}
}
public static ResultSet<dynamic> AddGraphEdge(GremlinClient GremlinClient, string FromVertexID, string ToVertexID, string EdgeLabel, Dictionary<string, string> Properties = null)
{
try
{
var query = GraphQueryBusinessLogic.CreateAddEdgeGraphQuery(FromVertexID, ToVertexID, EdgeLabel, Properties);
var results = TransactGraphQuery(GremlinClient, query);
return results;
}
catch (Exception)
{
throw;
}
}
public static string AddCommunicatorAndOrganization(string CommunicatorIdentity, GremlinClient GremlinClient)
{
string communicatorID = AddGraphVertex(GremlinClient, CommunicatorVertexLabel, CommunicatorIdentity);
//Extract the communicator's domain and transact that in
var communicatorOrganizationDomain = GetDomainFromEmailAddress(CommunicatorIdentity);
string communicatorOrganizationDomainID = AddGraphVertex(GremlinClient, OrganizationVertexLabel, communicatorOrganizationDomain);
var queryResults = GetGraphEdge(GremlinClient, communicatorID, communicatorOrganizationDomainID, CommunicatorOrganizationEdgeLabel);
//If we have no edge, add it
if (queryResults.Count == 0)
{
// Create an edge between the communicator and the domain
AddGraphEdge(GremlinClient, communicatorID, communicatorOrganizationDomainID, CommunicatorOrganizationEdgeLabel);
}
//If we have one edge, do nothing because the proper connection already exists
//If we have many edges, that is a problem
else if (queryResults.Count > 1)
{
//TODO: Add error logging
}
return communicatorID;
}
public static string AddCommunication(EmailSearch Communication, GremlinClient GremlinClient)
{
Dictionary<string, string> properties = new Dictionary<string, string>();
properties.Add(CommunicationVertexPartitionKeyProperty, Communication.PartitionKey);
properties.Add(CommunicationVertexRowKeyProperty, Communication.RowKey);
properties.Add(CommunicationVertexSubjectProperty, Communication.EmailSubject);
properties.Add(CommunicationVertexUTCTimeProperty, Communication.Timestamp.ToString());
properties.Add(CommunicationVertexYearProperty, Communication.Timestamp.Year.ToString());
properties.Add(CommunicationVertexMonthProperty, Communication.Timestamp.Month.ToString());
properties.Add(CommunicationVertexDayProperty, Communication.Timestamp.Day.ToString());
properties.Add(CommunicationVertexConversationIDProperty, Communication.EmailConversationId);
properties.Add(CommunicationVertexReferenceKey, Communication.ReferenceKey);
string communicationID = AddGraphVertex(GremlinClient, CommunicationVertexLabel, null, properties);
return communicationID;
}
public Dictionary<string, string> ProcessCommunicationsIntoGraphQueries(List<EmailSearch> Communications)
{
Dictionary<string, string> gremlinQueries = new Dictionary<string, string> { };
Dictionary<string, string> communicators = new Dictionary<string, string>();
Dictionary<string, string> organizations = new Dictionary<string, string>();
Dictionary<string, string> tags = new Dictionary<string, string>();
Dictionary<string, int> senderTag = new Dictionary<string, int>();
Dictionary<string, int> tagPrimaryRecipient = new Dictionary<string, int>();
Dictionary<string, int> tagSecondaryRecipient = new Dictionary<string, int>();
Dictionary<string, string> organizationCommunicators = new Dictionary<string, string>();
Dictionary<string, int> tagRelationships = new Dictionary<string, int>();
List<CommunicationGraphModel> communicationModels = new List<CommunicationGraphModel>();
// Clear the model
gremlinQueries.Add("Cleanup", "g.V().drop()");
// Preprocess the communications
BuildInteractionDictionaries(Communications, communicators, organizations, organizationCommunicators, tags, senderTag, tagPrimaryRecipient, tagSecondaryRecipient, tagRelationships);
foreach (var communicator in communicators)
{
if (communicator.Key != null && communicator.Key.Length > 0)
{
GenerateVertexInsertionQuery(gremlinQueries, communicator, "communicator");
}
}
foreach (var organization in organizations)
{
if (organization.Key != null && organization.Key.Length > 0)
{
GenerateVertexInsertionQuery(gremlinQueries, organization, "organization");
}
}
foreach (var tag in tags)
{
if (tag.Key != null && tag.Key.Length > 0)
{
GenerateVertexInsertionQuery(gremlinQueries, tag, "tag");
}
}
foreach (var item in organizationCommunicators)
{
GenerateEdgeInsertionQuery(gremlinQueries, item.Key, KeyBinder, "membership", null);
}
foreach (var item in senderTag)
{
Dictionary<string, string> edgeProperties = new Dictionary<string, string>
{
{ "sent", item.Value.ToString() }
};
GenerateEdgeInsertionQuery(gremlinQueries, item.Key, KeyBinder, "sender", edgeProperties);
}
foreach (var item in tagRelationships)
{
Dictionary<string, string> edgeProperties = new Dictionary<string, string>
{
{ "related to", item.Value.ToString() }
};
GenerateEdgeInsertionQuery(gremlinQueries, item.Key, KeyBinder, "related", edgeProperties);
}
// Get the non-duplcated key union of the primary and secondary recipient lists
var totalRecipientList = new List<string>(tagPrimaryRecipient.Keys).Union(new List<string>(tagSecondaryRecipient.Keys));
foreach (var item in totalRecipientList)
{
Dictionary<string, string> edgeProperties = new Dictionary<string, string>();
ProcessRecipientForEdgeQuery(item, tagPrimaryRecipient, "primary recipient", edgeProperties);
ProcessRecipientForEdgeQuery(item, tagSecondaryRecipient, "secondary recipient", edgeProperties);
GenerateEdgeInsertionQuery(gremlinQueries, item, KeyBinder, "recipient", edgeProperties);
}
Console.WriteLine(String.Format("Communicators [vertices]: {0}", communicators.Count));
Console.WriteLine(String.Format("Organizations [vertices]: {0}", organizations.Count));
Console.WriteLine(String.Format("Tags [vertices]: {0}", tags.Count));
Console.WriteLine(String.Format("Communicators->Organizations [edges]: {0}", organizationCommunicators.Count));
Console.WriteLine(String.Format("Communicators->Tags [edges]: {0}", organizationCommunicators.Count));
Console.WriteLine(String.Format("Tags->Communicators (primary recipients) [edges]: {0}", tagPrimaryRecipient.Count));
Console.WriteLine(String.Format("Tags->Communicators (secondary recipients) [edges]: {0}", tagSecondaryRecipient.Count));
Console.WriteLine(String.Format("Tags->Tags [edges]: {0}", tagRelationships.Count));
return gremlinQueries;
}
public enum InsertionQueryPropertyTypes { StringType, IntegerType };
private static void ProcessRecipientForEdgeQuery(string Key, Dictionary<string, int> Entries, string PropertyName, Dictionary<string, string> EdgeProperties)
{
if (Entries.ContainsKey(Key))
{
EdgeProperties.Add(PropertyName, Entries[Key].ToString());
}
}
private static void GenerateEdgeInsertionQuery(Dictionary<string, string> GremlinQueries, string LinkedVertices, string KeyBinder, string EdgeType, Dictionary<string, string> Properties)
{
// TODO Move this into GraphQueryBusinessLogic
var tuple = LinkedVertices.Split(new string[] { KeyBinder }, StringSplitOptions.None);
var key = String.Format("AddEdge {0}-{1}-{2}", tuple[0], EdgeType, tuple[1]);
StringBuilder queryValue = new StringBuilder();
//Create the base edge insertion query
queryValue.Append(String.Format("g.V('{0}').addE('{1}').to(g.V('{2}'))", tuple[0], EdgeType, tuple[1]));
//Append properties that should be added to the edge
if (Properties != null && Properties.Count > 0)
{
foreach (var propertyKey in Properties.Keys)
{
if (Int32.TryParse(Properties[propertyKey], out int intValue))
{
queryValue.Append(String.Format(".property('{0}',{1})", propertyKey, Properties[propertyKey]));
}
else
{
queryValue.Append(String.Format(".property('{0}','{1}')", propertyKey, Properties[propertyKey]));
}
}
}
GremlinQueries.Add(key, queryValue.ToString());
}
private static void GenerateEdgeInsertionQuery(Dictionary<string, string> GremlinQueries, string LinkedVertices, string KeyBinder, string EdgeType)
{
GenerateEdgeInsertionQuery(GremlinQueries, LinkedVertices, KeyBinder, EdgeType, null);
}
private static void GenerateVertexInsertionQuery(Dictionary<string, string> GremlinQueries, KeyValuePair<string, string> KVP, string VertexType, string PartitionName = null)
{
var query = GraphQueryBusinessLogic.CreateAddVertexGraphQuery(VertexType, KVP.Key, Guid.NewGuid().ToString(), PartitionName);
GremlinQueries.Add(String.Format("AddVertex {0}", KVP.Key), query);
}
//Communications, communicators, organizations, organizationCommunicators, tags, senderTag, tagPrimaryRecipient, tagSecondaryRecipient, tagRelationships
private static void BuildInteractionDictionaries(List<EmailSearch> Communications, Dictionary<string, string> Communicators, Dictionary<string, string> Organizations, Dictionary<string, string> OrganizationCommunicators, Dictionary<string, string> Tags, Dictionary<string, int> SenderTag, Dictionary<string, int> TagPrimaryRecipient, Dictionary<string, int> TagSecondaryRecipient, Dictionary<string, int> TagRelationships)
{
// Iterate through all the communications
foreach (var communication in Communications)
{
//Only process entries that have tags
if (communication.EmailTagCluster != null && communication.EmailTagCluster.Length > 0)
{
var communicationModel = new CommunicationGraphModel(communication);
//Add new communicators
AddStringToDictionary(Communicators, communicationModel.CommunicationSender);
AddStringListToDictionary(Communicators, communicationModel.ToRecipients);
AddStringListToDictionary(Communicators, communicationModel.CcRecipients);
//Add orgs and create org-communicator mappings
CreateCommunicatorOrganizationRelationship(Organizations, OrganizationCommunicators, communicationModel.CommunicationSender, KeyBinder);
if (communicationModel.ToRecipients != null)
{
foreach (var item in communicationModel.ToRecipients)
{
CreateCommunicatorOrganizationRelationship(Organizations, OrganizationCommunicators, item, KeyBinder);
}
}
if (communicationModel.CcRecipients != null)
{
foreach (var item in communicationModel.CcRecipients)
{
CreateCommunicatorOrganizationRelationship(Organizations, OrganizationCommunicators, item, KeyBinder);
}
}
//Add new tags and tag relationships
CreateTagRelationships(Tags, SenderTag, TagPrimaryRecipient, TagSecondaryRecipient, TagRelationships, communicationModel, KeyBinder);
}
}
}
private static void CreateTagRelationships(Dictionary<string, string> Tags, Dictionary<string, int> SenderTag, Dictionary<string, int> TagPrimaryRecipient, Dictionary<string, int> TagSecondaryRecipient, Dictionary<string, int> TagRelationships, CommunicationGraphModel CommunicationModel, string KeyBinder)
{
//Add new tags
AddStringListToDictionary(Tags, CommunicationModel.Tags);
//Process the tag sender and recipient relationships
foreach (var tag in CommunicationModel.Tags)
{
if (tag.Length > 0)
{
AddTagSender(SenderTag, CommunicationModel, tag);
AddTagRecipients(TagPrimaryRecipient, tag, CommunicationModel.ToRecipients);
AddTagRecipients(TagSecondaryRecipient, tag, CommunicationModel.CcRecipients);
}
}
// Only process relationships if there are multiple tags
if (CommunicationModel.Tags.Count > 1)
{
// Iterate over the list of tags associated with the communication
for (int i = 0; i < CommunicationModel.Tags.Count - 1; i++)
{
// Move forward in the list by one
for (int j = i + 1; j < CommunicationModel.Tags.Count; j++)
{
var key = CommunicationModel.Tags.ElementAt(i) + KeyBinder + CommunicationModel.Tags.ElementAt(j);
IncrementKeyedIntegerInDictionary(TagRelationships, key);
}
}
}
}
private static void AddTagSender(Dictionary<string, int> SenderTag, CommunicationGraphModel communicationModel, string tag)
{
string key = communicationModel.CommunicationSender + KeyBinder + tag;
IncrementKeyedIntegerInDictionary(SenderTag, key);
}
private static void IncrementKeyedIntegerInDictionary(Dictionary<string, int> KeyedDictionary, string key)
{
if (KeyedDictionary.ContainsKey(key))
{
KeyedDictionary[key] = KeyedDictionary[key] + 1;
}
else
{
KeyedDictionary[key] = 1;
}
}
private static void AddTagRecipients(Dictionary<string, int> DictionaryToPopulate, string tag, List<string> Recipients)
{
if (Recipients != null && Recipients.Count > 0)
{
string key = "";
foreach (var recipient in Recipients)
{
key = tag + KeyBinder + recipient;
IncrementKeyedIntegerInDictionary(DictionaryToPopulate, key);
}
}
}
private static void AddStringListToDictionary(Dictionary<string, string> DictionaryToPopulate, List<string> ItemsToAdd)
{
if (ItemsToAdd != null && ItemsToAdd.Count > 0)
{
foreach (var item in ItemsToAdd)
{
AddStringToDictionary(DictionaryToPopulate, item);
}
}
}
private static void AddStringToDictionary(Dictionary<string, string> DictionaryToPopulate, String ItemToAdd)
{
if (ItemToAdd != null && ItemToAdd.Length > 0)
{
if (!DictionaryToPopulate.ContainsKey(ItemToAdd))
{
DictionaryToPopulate.Add(ItemToAdd, ItemToAdd);
}
}
}
private bool AddEmailAddressToDictionary(Dictionary<string, string> EmailAddresses, string EmailAddressToAdd, bool ConvertToLowerCase = true)
{
if (ConvertToLowerCase)
{
EmailAddressToAdd = EmailAddressToAdd.ToLower();
}
if (!EmailAddresses.ContainsKey(EmailAddressToAdd))
{
EmailAddresses.Add(EmailAddressToAdd, EmailAddressToAdd);
return true;
}
return false;
}
public static List<string> ParseConcatenatedString(string ConcatenatedStrings, string Delimiter = null, bool MakeLowerCase = true, bool RemoveReservedCharacters = true, string ReplacementCharacters = "")
{
if (Delimiter == null)
{
Delimiter = CommunicationAddressDelimiter;
}
List<string> returnList = new List<string>();
if (ConcatenatedStrings != null && ConcatenatedStrings.Length > 0)
{
var entries = ConcatenatedStrings.Split(new string[] { Delimiter }, StringSplitOptions.None);
foreach (var entry in entries)
{
//Limiting total tag length
if (entry.Length <= MaximumTagLength)
{
var entryValue = entry;
entryValue = GraphQueryBusinessLogic.ConformStringForQuery(entryValue, MakeLowerCase, RemoveReservedCharacters, ReplacementCharacters);
returnList.Add(entryValue);
}
}
}
return returnList;
}
public static List<string> CreateCommunicationSendEdgeQuery(string SenderID, string RecipientID)
{
List<string> queries = new List<string>
{
GraphQueryBusinessLogic.CreateSenderRecipientEdgeGraphQuery(SenderID, RecipientID)
};
return queries;
}
public static List<string> CreateCommunicationTagEdgeQuery(string SenderID, string RecipientID, string TagID)
{
List<string> queries = new List<string>
{
GraphQueryBusinessLogic.CreateSenderTagEdgeGraphQuery(SenderID, TagID),
GraphQueryBusinessLogic.CreateTagRecipientEdgeGraphQuery(TagID, RecipientID)
};
return queries;
}
public static string GetDomainFromEmailAddress(String CommunicationSender)
{
if (CommunicationSender != null && CommunicationSender.Length > 0)
{
var atSymbolIndex = CommunicationSender.IndexOf("@");
if (atSymbolIndex > -1)
{
var domainSuffixDelimiterIndex = CommunicationSender.LastIndexOf(".");
// Process a result like someone.somewho@someplace.com
if (CommunicationSender.IndexOf(".", atSymbolIndex) == domainSuffixDelimiterIndex)
{
return CommunicationSender.Substring(atSymbolIndex + 1);
}
// Process a result like someone.somewho@something.someplace.com
else if (CommunicationSender.IndexOf(".", atSymbolIndex) < domainSuffixDelimiterIndex)
{
return CommunicationSender.Substring(CommunicationSender.IndexOf(".", atSymbolIndex) + 1);
}
}
}
return "";
}
public static void CreateCommunicatorOrganizationRelationship(Dictionary<string, string> Organizations, Dictionary<string, string> OrganizationCommunicators, string CommunicationSender, string KeyBinder)
{
if (CommunicationSender != null && CommunicationSender.Length > 0)
{
var domain = GetDomainFromEmailAddress(CommunicationSender);
if (domain != null && domain.Length > 0)
{
AddStringToDictionary(Organizations, domain);
var orgCommunicatorKey = domain + KeyBinder + CommunicationSender;
AddStringToDictionary(OrganizationCommunicators, orgCommunicatorKey);
}
}
}
public static Task<ResultSet<dynamic>> SubmitRequest(GremlinClient gremlinClient, string query)
{
try
{
return gremlinClient.SubmitAsync<dynamic>(query);
}
catch (ResponseException e)
{
Console.WriteLine("\tRequest Error!");
// Print the Gremlin status code.
Console.WriteLine($"\tStatusCode: {e.StatusCode}");
// On error, ResponseException.StatusAttributes will include the common StatusAttributes for successful requests, as well as
// additional attributes for retry handling and diagnostics.
// These include:
// x-ms-retry-after-ms : The number of milliseconds to wait to retry the operation after an initial operation was throttled. This will be populated when
// : attribute 'x-ms-status-code' returns 429.
// x-ms-activity-id : Represents a unique identifier for the operation. Commonly used for troubleshooting purposes.
PrintStatusAttributes(e.StatusAttributes);
Console.WriteLine($"\t[\"x-ms-retry-after-ms\"] : { GetValueAsString(e.StatusAttributes, "x-ms-retry-after-ms")}");
Console.WriteLine($"\t[\"x-ms-activity-id\"] : { GetValueAsString(e.StatusAttributes, "x-ms-activity-id")}");
throw;
}
}
private static void PrintStatusAttributes(IReadOnlyDictionary<string, object> attributes)
{
Console.WriteLine($"\tStatusAttributes:");
Console.WriteLine($"\t[\"x-ms-status-code\"] : { GetValueAsString(attributes, "x-ms-status-code")}");
Console.WriteLine($"\t[\"x-ms-total-request-charge\"] : { GetValueAsString(attributes, "x-ms-total-request-charge")}");
}
public static string GetValueAsString(IReadOnlyDictionary<string, object> dictionary, string key)
{
return JsonConvert.SerializeObject(GetValueOrDefault(dictionary, key));
}
public static object GetValueOrDefault(IReadOnlyDictionary<string, object> dictionary, string key)
{
if (dictionary.ContainsKey(key))
{
return dictionary[key];
}
return null;
}
public static Uri GetStorageEndpoint()
{
return AzureTableDataUtilities.GetStorageAccount().TableEndpoint;
}
public static async Task<List<EmailSearch>> RetrieveEmailsAsync()
{
List<EmailSearch> returnList = null;
var tagTable = AzureTableDataUtilities.GetTagTable();
var tagQuery = new AzureTableTagQuery();
returnList = await tagQuery.GetTaggedCommunicationsAsync(tagTable);
return returnList;
}
public static void TransactGraphQueries(Dictionary<string, string> GremlinQueries, String Hostname, int Port, String AuthKey, String Database, String Collection, bool VerboseReporting = false)
{
var gremlinClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(Hostname, Port, AuthKey, Database, Collection);
foreach (var query in GremlinQueries)
{
Console.WriteLine(String.Format("Running this query: {0}: {1}", query.Key, query.Value));
TransactGraphQuery(gremlinClient, query.Value, VerboseReporting);
}
}
public static ResultSet<dynamic> TransactGraphQuery(GremlinClient gremlinClient, string query, bool VerboseReporting = false)
{
//Console.WriteLine("Graph transaction: " + query);
// Create async task to execute the Gremlin query.
var resultSet = SubmitRequest(gremlinClient, query).Result;
if (VerboseReporting)
{
if (resultSet.Count > 0)
{
Console.WriteLine("\tResult:");
foreach (var result in resultSet)
{
// The vertex results are formed as Dictionaries with a nested dictionary for their properties
var output = JsonConvert.SerializeObject(result);
Console.WriteLine($"\t{output}");
}
Console.WriteLine();
}
// Print the status attributes for the result set.
// This includes the following:
// x-ms-status-code : This is the sub-status code which is specific to Cosmos DB.
// x-ms-total-request-charge : The total request units charged for processing a request.
PrintStatusAttributes(resultSet.StatusAttributes);
Console.WriteLine();
}
return resultSet;
}
}
}

Просмотреть файл

@ -0,0 +1,99 @@
using CELA_Knowledge_Management_Data_Services.DataUtilities;
using CELA_Knowledge_Management_Data_Services.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
namespace CELA_Knowledge_Management_Data_Services.BusinessLogic
{
public class GraphAnalysisBusinessLogic
{
public static List<TagRecipient> GetTopicRecipients(string Topic, IGraphConfiguration GraphConfiguration)
{
List<TagRecipient> tagRecipients = new List<TagRecipient>();
using (var tagHiveClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(GraphConfiguration))
{
//TODO Update this query to find most common recipients of the topic
string query = string.Format("g.V(\"{0}\").outE(\"recipient\")", Topic);
var results = CommunicationProcessingBusinessLogic.SubmitRequest(tagHiveClient, query).Result;
if (results.Count > 0)
{
foreach (var item in results)
{
TagRecipient tagRecipient = JsonConvert.DeserializeObject<TagRecipient>(JsonConvert.SerializeObject(item));
tagRecipients.Add(tagRecipient);
}
}
}
return tagRecipients;
}
public static List<string> GetTopicSenders(string Topic, IGraphConfiguration GraphConfiguration)
{
List<string> tagSenders = new List<string>();
using (var tagHiveClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(GraphConfiguration))
{
string query = GraphQueryBusinessLogic.GetTopicSendersGraphQuery(Topic);
var results = CommunicationProcessingBusinessLogic.SubmitRequest(tagHiveClient, query).Result;
if (results.Count > 0)
{
foreach (var item in results)
{
//TagSender tagSender = JsonConvert.DeserializeObject<TagSender>(JsonConvert.SerializeObject(item));
tagSenders.Add(item);
}
}
}
return tagSenders;
}
public static DocumentGraphModelList GetDocumentsForTag(IGraphConfiguration GraphConfiguration, string Tag)
{
using (var tagHiveClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(GraphConfiguration))
{
string query = GraphQueryBusinessLogic.GetDocumentsForTagGraphQuery(Tag);
var results = CommunicationProcessingBusinessLogic.SubmitRequest(tagHiveClient, query).Result;
var jsonString = JsonConvert.SerializeObject(results);
return JsonConvert.DeserializeObject<DocumentGraphModelList>(jsonString);
}
}
public static MatterGraphModel GetMatters(IGraphConfiguration GraphConfiguration)
{
using (var tagHiveClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(GraphConfiguration))
{
string query = GraphQueryBusinessLogic.GetMattersGraphQuery();
var results = CommunicationProcessingBusinessLogic.SubmitRequest(tagHiveClient, query).Result;
var jsonString = JsonConvert.SerializeObject(results);
return JsonConvert.DeserializeObject<MatterGraphModel>(jsonString);
}
}
public static Dictionary<string, int> GetTopicSendersWithSentValues(string Topic, IGraphConfiguration GraphConfiguration)
{
Dictionary<string, int> tagSenders = new Dictionary<string, int>();
using (var tagHiveClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(GraphConfiguration))
{
string query = GraphQueryBusinessLogic.GetTopicSendersGraphQueryWithSentValues(Topic);
var results = CommunicationProcessingBusinessLogic.SubmitRequest(tagHiveClient, query).Result;
if (results.Count > 0)
{
foreach (var resultsetItem in results)
{
foreach (var item in resultsetItem)
{
tagSenders.Add(((KeyValuePair<string, object>)item).Key, int.Parse(((KeyValuePair<string, object>)item).Value.ToString()));
}
}
}
}
return tagSenders;
}
}
}

Просмотреть файл

@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CELA_Knowledge_Management_Data_Services.BusinessLogic
{
public class GraphQueryBusinessLogic
{
public static string CreatePropertyClauseForGraphQuery(KeyValuePair<string, string> Property)
{
if (Int32.TryParse(Property.Value, out int intValue) || Double.TryParse(Property.Value, out double doubleValue))
{
return String.Format(".property('{0}', {1})", Property.Key, Property.Value);
}
else
{
return String.Format(".property('{0}', '{1}')", Property.Key, ConformStringForQuery(Property.Value));
}
}
public static string ConformStringForQuery(string Value, bool MakeLowerCase = true, bool RemoveReservedCharacters = true, string ReplacementCharacters = "")
{
if (Value != null && Value.Length > 0)
{
if (MakeLowerCase)
{
Value = Value.ToLower();
}
if (RemoveReservedCharacters)
{
Value = Value.Replace("#", ReplacementCharacters);
//Value = Value.Replace("/", ReplacementCharacters);
Value = Value.Replace("'", ReplacementCharacters);
Value = Value.Replace("?", ReplacementCharacters);
Value = Value.Replace("$", ReplacementCharacters);
Value = Value.Replace("&", ReplacementCharacters);
}
}
return Value;
}
public static string CreateVertexIfDoesNotExistGraphQuery(string VertexType, string Name, string GUID, Dictionary<string, string> Properties = null, string PartitionName = null)
{
// TODO Add code that cleans up the property values to remove problematic characters
var query = new StringBuilder();
query.Append(String.Format("g.V().has('{0}', '{3}', '{1}').fold().coalesce(unfold(), addV('{0}').property('{3}', '{1}').property('{4}', '{2}')", VertexType, ConformStringForQuery(Name), GUID, CommunicationProcessingBusinessLogic.VertexNameProperty, CommunicationProcessingBusinessLogic.VertexIDProperty));
if (PartitionName != null && PartitionName.Length > 0)
{
if (Properties == null)
{
Properties = new Dictionary<string, string>();
}
Properties.Add(CommunicationProcessingBusinessLogic.GraphPartitionKeyProperty, ConformStringForQuery(PartitionName));
}
if (Properties != null && Properties.Keys.Count > 0)
{
foreach (var Property in Properties)
{
query.Append(CreatePropertyClauseForGraphQuery(Property));
}
}
query.Append(")");
return query.ToString();
}
public static string CreateAddVertexGraphQuery(string Key, string VertexType, string GUID, string PartitionName)
{
var query = new StringBuilder();
query.Append(String.Format("g.addV('{0}').property('id', '{1}').property('guid', '{2}')", VertexType, Key, GUID));
if (PartitionName != null && PartitionName.Length > 0)
{
query.Append(String.Format(".property('partitionKey', '{0}')", PartitionName));
}
return query.ToString();
}
public static string CreateAddEdgeGraphQuery(string FromVertexID, string ToVertexID, string EdgeLabel, Dictionary<string, string> Properties)
{
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.Append( string.Format("g.V('{0}').addE('{2}').to(g.V('{1}')", FromVertexID, ToVertexID, EdgeLabel));
if (Properties != null && Properties.Count >0)
{
foreach (var property in Properties)
{
queryBuilder.Append(CreatePropertyClauseForGraphQuery(property));
}
}
queryBuilder.Append(")");
return queryBuilder.ToString();
}
public static string CreateRetrieveVertexGraphQuery(string VertexLabel, string PropertyName, string PropertyValue)
{
return string.Format("g.V().haslabel('{0}').has('{1}', '{2}')", VertexLabel, PropertyName, PropertyValue);
}
public static string CreateRetrieveEdgeGraphQuery(string FromVertexID, string ToVertexID, string EdgeLabel)
{
return string.Format("g.V().has('id', '{0}').outE().as ('e').has('label', '{2}').inV().has('id', '{1}').select('e')", FromVertexID, ToVertexID, EdgeLabel);
}
public static string CreateUpdateEdgeGraphQuery(string FromVertexID, string ToVertexID, string EdgeLabel, Dictionary<string, string> Properties)
{
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.Append(CreateRetrieveEdgeGraphQuery(FromVertexID, ToVertexID, EdgeLabel));
if (Properties != null && Properties.Count > 0)
{
foreach (var property in Properties)
{
queryBuilder.Append(CreatePropertyClauseForGraphQuery(property));
}
}
queryBuilder.Append(".iterate()");
return queryBuilder.ToString();
}
/// <summary>Creates the sender recipient graph query.</summary>
/// <param name="SenderID">The sender identifier.</param>
/// <param name="RecipientID">The recipient identifier.</param>
/// <returns></returns>
public static string CreateSenderRecipientEdgeGraphQuery(string SenderID, string RecipientID)
{
return string.Format("g.V('{0}').addE('sends').to(g.V('{1}'))", SenderID, RecipientID);
}
/// <summary>Creates the sender tag graph query.</summary>
/// <param name="SenderID">The sender identifier.</param>
/// <param name="TagID">The tag identifier.</param>
/// <returns></returns>
public static string CreateSenderTagEdgeGraphQuery(string SenderID, string TagID)
{
return string.Format("g.V('{0}').addE('sends').to(g.V('{1}'))", SenderID, TagID);
}
/// <summary>Creates the tag recipient graph query.</summary>
/// <param name="TagID">The tag identifier.</param>
/// <param name="RecipientID">The recipient identifier.</param>
/// <returns></returns>
public static string CreateTagRecipientEdgeGraphQuery(string TagID, string RecipientID)
{
return string.Format("g.V('{0}').addE('sends').to(g.V('{1}'))", TagID, RecipientID);
}
/// <summary>Gets the topic senders graph query.</summary>
/// <param name="topic">The topic.</param>
/// <returns></returns>
public static string GetTopicSendersGraphQuery(string topic)
{
return string.Format("g.V().has('name', '{0}').inE('relates to').outV().inE('sends').outV().project('a').by('name').select('a').dedup()", topic);
//return string.Format("g.V().has('name', '{0}').inE('relates to').outV().inE('sends').outV()", topic);
//return string.Format("g.V('{0}').inE('sender').order().by('sent', decr)", topic);
}
public static string GetTopicSendersGraphQueryWithSentValues(string topic)
{
return string.Format("g.V().has('name', '{0}').inE('relates to').outV().inE('sends').outV().project('a').by('name').select('a').groupCount()", topic);
}
public static string GetMattersGraphQuery()
{
return string.Format("g.V().haslabel('{0}')", CommunicationProcessingBusinessLogic.MatterVertexLabel);
}
public static string GetDocumentsForTagGraphQuery(string tag)
{
return string.Format("g.V().haslabel('{1}').has('{2}', '{0}').inE().has('label', '{3}').outV().outE().inV().haslabel('{4}')", tag, CommunicationProcessingBusinessLogic.TagVertexLabel, CommunicationProcessingBusinessLogic.VertexNameProperty, CommunicationProcessingBusinessLogic.CommunicationTagEdgeLabel, CommunicationProcessingBusinessLogic.DocumentVertexLabel);
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>CELA_Knowledge_Management_Data_Services</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Gremlin.Net" Version="3.4.0" />
<PackageReference Include="Microsoft.Bot.Builder" Version="4.1.5" />
<PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />
</ItemGroup>
</Project>

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CELA_Knowledge_Management_Data_Services.DataUtilities
{
public interface IGraphConfiguration
{
string GetGraphDatabaseHostname();
string GetGraphDatabaseAccessKey();
string GetGraphDatabaseCollectionName();
string GetGraphDatabaseName();
int GetGraphDatabasePort();
}
}

Просмотреть файл

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CELA_Knowledge_Management_Data_Services.DataUtilities
{
public interface ITableConfiguration
{
string GetTableAccessKey();
string GetTableHostname();
string GetTableName();
}
}

Просмотреть файл

@ -0,0 +1,46 @@
using Microsoft.Bot.Builder;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Text;
namespace CELA_Knowledge_Management_Data_Services.DataUtilities
{
public class LUISDataUtilities
{
// Based upon https://pauliom.com/2018/11/06/extracting-an-entity-from-luis-in-bot-framework/
public static int GetNumberEntityAsInt(RecognizerResult luisResult, string entityKey, string valuePropertyName = "text")
{
int number = -1;
if (luisResult != null)
{
var data = luisResult.Entities as IDictionary<string, JToken>;
if (data.TryGetValue("number", out JToken value))
{
int.TryParse(value.First.ToString(), out number);
}
}
return number;
}
public static string GetEntityAsString(RecognizerResult luisResult, string ValuePropertyName = "text")
{
string returnValue = "";
if (luisResult != null)
{
var data = luisResult.Entities as IDictionary<string, JToken>;
if (data.TryGetValue(ValuePropertyName, out JToken value))
{
if (value.First != null)
{
returnValue = value.First.ToString();
}
}
}
return returnValue;
}
}
}

Просмотреть файл

@ -0,0 +1,203 @@
using Microsoft.WindowsAzure.Storage.Table;
using System;
using System.Collections.Generic;
using System.Text;
namespace CELA_Knowledge_Management_Data_Services.Models
{
/// <summary>
/// An object that encapsulates the behaviors related to parsing an email for tag usage.
/// </summary>
public abstract class EmailSearch : TableEntity
{
private string emailSender;
private string emailSentTime;
/// <summary>
/// Gets or sets a value indicating whether to exclude prior emails that may be in the text string from search function. Note that this only works on English emails because the parsing function is pretty simple, and breaks chunks on indicators like "From:".
/// </summary>
/// <value>
/// <c>true</c> if exclude prior emails from search; otherwise, <c>false</c>.
/// </value>
public bool ExcludePriorEmailsFromSearch { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to remove duplicate tags found from the response.
/// </summary>
/// <value>
/// <c>true</c> if remove duplicates; otherwise, <c>false</c>.
/// </value>
public bool RemoveDuplicates { get; set; }
/// <summary>
/// Gets or sets a value indicating whether persist results server side, thus negating the need to persist results by the caller.
/// </summary>
/// <value>
/// <c>true</c> if persist results server side; otherwise, <c>false</c>.
/// </value>
public bool PersistResultsServerSide { get; set; }
/// <summary>
/// Gets or sets the email sender's email address.
/// </summary>
/// <value>
/// The email sender.
/// </value>
public string EmailSender
{ get; set; }
/// <summary>
/// Gets or sets the email sent time (ZULU).
/// </summary>
/// <value>
/// The email sent time.
/// </value>
public string EmailSentTime
{ get; set; }
/// <summary>
/// Gets or sets the email To line recipients' email addresses.
/// </summary>
/// <value>
/// The email to recipients.
/// </value>
public string EmailToRecipients { get; set; }
/// <summary>
/// Gets or sets the email Cc line recipients's email addresses.
/// </summary>
/// <value>
/// The email cc recipients.
/// </value>
public string EmailCcRecipients { get; set; }
/// <summary>
/// Gets or sets the email subject.
/// </summary>
/// <value>
/// The email subject.
/// </value>
public string EmailSubject { get; set; }
/// <summary>
/// Gets or sets the email body text.
/// </summary>
/// <value>
/// The email body text.
/// </value>
public string EmailBodyText { get; set; }
/// <summary>
/// Gets or sets the email sender organization.
/// </summary>
/// <value>
/// The email sender organization.
/// </value>
public string EmailSenderOrganization { get; set; }
/// <summary>
/// Gets or sets the email sender team.
/// </summary>
/// <value>
/// The email sender team.
/// </value>
public string EmailSenderTeam { get; set; }
/// <summary>
/// Gets or sets the email sender group.
/// </summary>
/// <value>
/// The email sender group.
/// </value>
public string EmailSenderGroup { get; set; }
/// <summary>
/// Gets or sets the email message identifier.
/// </summary>
/// <value>
/// The email message identifier.
/// </value>
public string EmailMessageId { get; set; }
/// <summary>
/// Gets or sets the email conversation identifier.
/// </summary>
/// <value>
/// The email conversation identifier.
/// </value>
public string EmailConversationId { get; set; }
/// <summary>
/// Gets or sets the email tag cluster, a string with all of the tags used, each separated by a space.
/// </summary>
/// <value>
/// The email tag cluster.
/// </value>
public string EmailTagCluster { get; set; }
/// <summary>Gets or sets the API version recorded in the client tier.</summary>
/// <value>The API version.</value>
public string APIVersion { get; set; }
/// <summary>Gets or sets the service API version.</summary>
/// <value>The service API version.</value>
public string ServiceAPIVersion { get; set; }
/// <summary>Gets or sets the reference key used to correlate this with other knowledge management artifacts.</summary>
/// <value>The reference key.</value>
public string ReferenceKey { get; set; }
/// <summary>Gets or sets the matter identifier.</summary>
/// <value>The matter identifier.</value>
public string MatterId { get; set; }
/// <summary>Gets or sets the tag start token used to denote tag starts.</summary>
/// <value>The tag start token.</value>
public string TagStartToken { get; set; }
}
public class TagSearchByDeclaredTag : EmailSearch
{
public TagSearchByDeclaredTag(string emailAddress, string emailSentTime)
{
this.PartitionKey = emailAddress;
this.RowKey = emailSentTime;
}
public string Tag { get; set; }
}
public class TagsSearchByTagStartToken : EmailSearch
{
public TagsSearchByTagStartToken(string emailAddress, string emailSentTime)
{
this.PartitionKey = emailAddress;
this.RowKey = emailSentTime;
}
public bool OnlyReturnMatterTags { get; set; }
}
/// <summary>A custom subclass of EmailSearch used to enable ordinal searches of email text (sequenced tags).</summary>
public class TagsSearchByTagStartTokenOrdinal : EmailSearch
{
public TagsSearchByTagStartTokenOrdinal()
{
}
/// <summary>Initializes a new instance of the <see cref="TagsSearchByTagStartTokenOrdinal"/> class.</summary>
/// <param name="emailAddress">The email address.</param>
/// <param name="emailSentTime">The email sent time.</param>
public TagsSearchByTagStartTokenOrdinal(string emailAddress, string emailSentTime)
{
this.PartitionKey = emailAddress;
this.RowKey = emailSentTime;
}
/// <summary>Gets or sets the size of the minimum tag set expected to be found.</summary>
/// <value>The size of the tag set.</value>
public string TagSetSize { get; set; }
/// <summary>Gets or sets the ordinal email tag cluster found by the search.</summary>
/// <value>The email tag cluster ordinal.</value>
public string EmailTagClusterOrdinal { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,98 @@
using CELA_Knowledge_Management_Data_Services.BusinessLogic;
using System;
using System.Collections.Generic;
using System.Text;
namespace CELA_Knowledge_Management_Data_Services.Models
{
public class CommunicationGraphModel
{
public CommunicationGraphModel()
{ }
public CommunicationGraphModel(EmailSearch Communication)
{
if (Communication.EmailSender != null && Communication.EmailSender.Length > 0)
{
CommunicationSender = Communication.EmailSender.ToLower();
}
if (Communication.EmailToRecipients != null && Communication.EmailToRecipients.Length > 0)
{
ToRecipients = CommunicationProcessingBusinessLogic.ParseConcatenatedString(Communication.EmailToRecipients, CommunicationAddressDelimiter);
}
if (Communication.EmailCcRecipients != null && Communication.EmailCcRecipients.Length > 0)
{
CcRecipients = CommunicationProcessingBusinessLogic.ParseConcatenatedString(Communication.EmailCcRecipients, CommunicationAddressDelimiter);
}
if (Communication.EmailTagCluster != null && Communication.EmailTagCluster.Length > 0)
{
Tags = CommunicationProcessingBusinessLogic.ParseConcatenatedString(Communication.EmailTagCluster, TagDelimiter);
}
}
public const string CommunicationAddressDelimiter = ";";
public const string TagDelimiter = " ";
public string CommunicationSender { get; set; }
public List<string> ToRecipients { get; set; }
public List<string> CcRecipients { get; set; }
public List<string> Tags { get; set; }
}
public class TagRecipients
{
public TagRecipient[] Recipients { get; set; }
}
public class TagRecipient
{
public string id { get; set; }
public string label { get; set; }
public string type { get; set; }
public string inVLabel { get; set; }
public string outVLabel { get; set; }
public string inV { get; set; }
public string outV { get; set; }
public TagRecipientProperties properties { get; set; }
}
public class TagRecipientProperties
{
public int primaryrecipient { get; set; }
public int secondaryrecipient { get; set; }
}
public class TagSenders
{
public TagSender[] Senders { get; set; }
}
public class TagSender
{
public string id { get; set; }
public string label { get; set; }
public string type { get; set; }
public string inVLabel { get; set; }
public string outVLabel { get; set; }
public string inV { get; set; }
public string outV { get; set; }
public TagSenderProperties properties { get; set; }
}
public class TagSenderProperties
{
public int sent { get; set; }
}
public class Document
{
public string id { get; set; }
public string name { get; set; }
public string type { get; set; }
public string sharepointlibrary { get; set; }
public string sharepointlibrarypath { get; set; }
public string referenceKey { get; set; }
public string matter { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CELA_Knowledge_Management_Data_Services.Models
{
public class DocumentGraphModelList : List<DocumentGraphModel>
{
}
//public class Rootobject
//{
// public Class1[] Property1 { get; set; }
//}
public class DocumentGraphModel
{
public string id { get; set; }
public string label { get; set; }
public string type { get; set; }
public DocumentGraphModelProperties properties { get; set; }
}
public class DocumentGraphModelProperties
{
public DocumentGraphModelName[] name { get; set; }
public DocumentGraphModelType[] type { get; set; }
public Library[] library { get; set; }
public Path[] path { get; set; }
public DocumentGraphModelKey[] key { get; set; }
}
public class DocumentGraphModelName
{
public string id { get; set; }
public string value { get; set; }
}
public class DocumentGraphModelType
{
public string id { get; set; }
public string value { get; set; }
}
public class Library
{
public string id { get; set; }
public string value { get; set; }
}
public class Path
{
public string id { get; set; }
public string value { get; set; }
}
public class DocumentGraphModelKey
{
public string id { get; set; }
public string value { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CELA_Knowledge_Management_Data_Services.Models
{
public class MatterGraphModel : List<Matter>
{
}
public class Matter
{
public string id { get; set; }
public string label { get; set; }
public string type { get; set; }
public Properties properties { get; set; }
}
public class Properties
{
public Name[] name { get; set; }
}
public class Name
{
public string id { get; set; }
public string value { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CELA_Knowledge_Management_Models</RootNamespace>
<AssemblyName>CELA-Knowledge_Management_Models</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="KMArtifact.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CELA_Knowledge_Management_Models
{
class KMArtifact
{
}
}

Просмотреть файл

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CELA-Knowledge_Management_Models")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CELA-Knowledge_Management_Models")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a93c0e6a-6afe-4f64-b735-0cf8119ad021")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CELA_Knowledge_Managment.BusinessLogic
{
public class MatterIdentificationBL
{
public const string MatterPrefix = "mid-";
public static bool ValidateMatterID(string TagStartToken,string MatterID)
{
//Example MID-04327-G4V9J7
if (MatterID.ToLower().StartsWith(TagStartToken + MatterPrefix))
{
return true;
}
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4F7269FB-67B7-465F-BF25-7ECD70407896}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CELA_Knowledge_Managment</RootNamespace>
<AssemblyName>CELA-Knowledge_Managment</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BusinessLogic\MatterIdentificationBL.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CELA-Knowledge_Managment")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CELA-Knowledge_Managment")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4f7269fb-67b7-465f-bf25-7ecd70407896")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,85 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CELA-Tags_Service_Models", "CELA-Tags_Service_Models\CELA-Tags_Service_Models.csproj", "{8556D4E4-0D3B-4531-B80C-893B1217F839}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA-Tags_Parsing_Service", "CELA-Tags_Parsing_Service\CELA-Tags_Parsing_Service.csproj", "{78E19CDA-49E8-4233-9BB1-16D6E712D560}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA-Tags_Parsing_ServiceTests", "CELA-Tags_Parsing_ServiceTests\CELA-Tags_Parsing_ServiceTests.csproj", "{6A9BC29F-9B35-420A-92F4-A8DCEC9C64F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA_Tags_Parsing_ServiceTestUtilities", "CELA_Tags_Parsing_ServiceTestUtilities\CELA_Tags_Parsing_ServiceTestUtilities.csproj", "{9B8DF1AA-85B1-4A60-8BC8-A66AEFE91C47}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA-Knowledge_Management_Models", "CELA-Knowledge_Management_Models\CELA-Knowledge_Management_Models.csproj", "{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA-Knowledge_Managment", "CELA-Knowledge_Managment\CELA-Knowledge_Managment.csproj", "{4F7269FB-67B7-465F-BF25-7ECD70407896}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CELA-Knowledge_Management_Assistant", "CELA-Knowledge_Management_Assistant\CELA-Knowledge_Management_Assistant.csproj", "{8739C9C7-06D4-4053-A469-B4BF7C4BC556}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CELA_Tag_Hive_Graph_Data_Processing", "CELA-Tag_Hive_Data_Processing\CELA_Tag_Hive_Graph_Data_Processing.csproj", "{3AD4D3B7-7252-43DA-8D58-79A91ED8BFFE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CELA-Knowledge_Management_Data_Services", "CELA-Knowledge_Management_Data_Services\CELA-Knowledge_Management_Data_Services.csproj", "{6D8BC8A4-9750-4560-A544-7E53CD47948D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA-Knowledge_Management_Data_Servicestests", "CELA-Knowledge_Management_Data_Services.tests\CELA-Knowledge_Management_Data_Servicestests.csproj", "{C58D9225-E2A2-417C-8745-D78A091BAB72}"
EndProject
Project("{F5034706-568F-408A-B7B3-4D38C6DB8A32}") = "CELA-Tag_Parsing_Service_Configuration_Utilities", "CELA-Tag_Parsing_Service_Configuration_Utilities\CELA-Tag_Parsing_Service_Configuration_Utilities.pssproj", "{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8556D4E4-0D3B-4531-B80C-893B1217F839}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8556D4E4-0D3B-4531-B80C-893B1217F839}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8556D4E4-0D3B-4531-B80C-893B1217F839}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8556D4E4-0D3B-4531-B80C-893B1217F839}.Release|Any CPU.Build.0 = Release|Any CPU
{78E19CDA-49E8-4233-9BB1-16D6E712D560}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{78E19CDA-49E8-4233-9BB1-16D6E712D560}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78E19CDA-49E8-4233-9BB1-16D6E712D560}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78E19CDA-49E8-4233-9BB1-16D6E712D560}.Release|Any CPU.Build.0 = Release|Any CPU
{6A9BC29F-9B35-420A-92F4-A8DCEC9C64F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A9BC29F-9B35-420A-92F4-A8DCEC9C64F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A9BC29F-9B35-420A-92F4-A8DCEC9C64F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A9BC29F-9B35-420A-92F4-A8DCEC9C64F0}.Release|Any CPU.Build.0 = Release|Any CPU
{9B8DF1AA-85B1-4A60-8BC8-A66AEFE91C47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B8DF1AA-85B1-4A60-8BC8-A66AEFE91C47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B8DF1AA-85B1-4A60-8BC8-A66AEFE91C47}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B8DF1AA-85B1-4A60-8BC8-A66AEFE91C47}.Release|Any CPU.Build.0 = Release|Any CPU
{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}.Release|Any CPU.Build.0 = Release|Any CPU
{4F7269FB-67B7-465F-BF25-7ECD70407896}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4F7269FB-67B7-465F-BF25-7ECD70407896}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F7269FB-67B7-465F-BF25-7ECD70407896}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F7269FB-67B7-465F-BF25-7ECD70407896}.Release|Any CPU.Build.0 = Release|Any CPU
{8739C9C7-06D4-4053-A469-B4BF7C4BC556}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8739C9C7-06D4-4053-A469-B4BF7C4BC556}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8739C9C7-06D4-4053-A469-B4BF7C4BC556}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8739C9C7-06D4-4053-A469-B4BF7C4BC556}.Release|Any CPU.Build.0 = Release|Any CPU
{3AD4D3B7-7252-43DA-8D58-79A91ED8BFFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3AD4D3B7-7252-43DA-8D58-79A91ED8BFFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3AD4D3B7-7252-43DA-8D58-79A91ED8BFFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3AD4D3B7-7252-43DA-8D58-79A91ED8BFFE}.Release|Any CPU.Build.0 = Release|Any CPU
{6D8BC8A4-9750-4560-A544-7E53CD47948D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D8BC8A4-9750-4560-A544-7E53CD47948D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D8BC8A4-9750-4560-A544-7E53CD47948D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D8BC8A4-9750-4560-A544-7E53CD47948D}.Release|Any CPU.Build.0 = Release|Any CPU
{C58D9225-E2A2-417C-8745-D78A091BAB72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C58D9225-E2A2-417C-8745-D78A091BAB72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C58D9225-E2A2-417C-8745-D78A091BAB72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C58D9225-E2A2-417C-8745-D78A091BAB72}.Release|Any CPU.Build.0 = Release|Any CPU
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {85904322-8A45-4773-8781-BC14400EB7FB}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<ApplicationIcon />
<StartupObject />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Gremlin.Net" Version="3.4.0" />
<PackageReference Include="Microsoft.Azure.CosmosDB.BulkExecutor" Version="1.4.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CELA-Knowledge_Management_Data_Services\CELA-Knowledge_Management_Data_Services.csproj" />
<ProjectReference Include="..\CELA-Tags_Parsing_Service\CELA-Tags_Parsing_Service.csproj" />
<ProjectReference Include="..\CELA-Tags_Service_Models\CELA-Tags_Service_Models.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,57 @@
https://github.com/tinkerpop/gremlin/wiki/Gremlin-Steps
http://tinkerpop.apache.org/docs/3.1.0-incubating/tutorials-getting-started.html
// Get a vertex
g.V('testemail@microsoft.com')
// Get all communicators
g.V().hasLabel('communicator').values('id')
// Get all tags
g.V().hasLabel('tag')
// Get all tags, only showing the id field
g.V().hasLabel('tag').values('id')
// Get a specific tag
g.V().hasLabel('tag').has('id', eq('tagulous'))
g.V('testemail@microsoft.com').outE('sends').inV().hasLabel('tag')
// Get the most commonly sent tags
g.V().outE("sender").order().by('sent', decr)
// Get all edges labeled recipient
g.V().inE("recipient")
// Get all edges
g.E()
// Get all of the communicators who have received a tag from the sender
g.V('testemail@microsoft.com').out().hasLabel('tag').out().hasLabel('communicator')
//Get the communicators who receive the most repeat tag exposure
g.E().hasLabel('recipient').has('primary recipient', gt(1))
//Get the edges that branch off "diversity" vertex
g.V("diversity").outE("recipient").has('primary recipient', gt(1))
//Get the vertices that branch off "diversity" vertex
g.V("diversity").outE("recipient").has('primary recipient', gt(1)).inV()
// Does not currently work
// Should get all of the recipients of the selected tag
g.V().hasLabel('tag').has('id', eq('tagulous')).outE('primary recipient').inV().hasLabel('communicator')
//Graph Version 2
//Get the people who send emails containing the tag the most
g.V().has('name', '{0}').inE('relates to').outV().inE('sends').outV().project('a').by('name').select('a').groupCount()
//Get the list of tags
g.V().haslabel('tag').project('name').by('name')
//Group the conversations that are associated with a conversation id
g.V().has('label', 'communication').project('a').by('conversation id').select('a').groupCount()

Просмотреть файл

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CELA_Tag_Hive_Graph_Data_Processing
{
public class TagRecipients
{
public TagRecipient[] Recipients { get; set; }
}
public class TagRecipient
{
public string id { get; set; }
public string label { get; set; }
public string type { get; set; }
public string inVLabel { get; set; }
public string outVLabel { get; set; }
public string inV { get; set; }
public string outV { get; set; }
public TagRecipientProperties properties { get; set; }
}
public class TagRecipientProperties
{
public int primaryrecipient { get; set; }
public int secondaryrecipient { get; set; }
}
public class TagSenders
{
public TagSender[] Senders { get; set; }
}
public class TagSender
{
public string id { get; set; }
public string label { get; set; }
public string type { get; set; }
public string inVLabel { get; set; }
public string outVLabel { get; set; }
public string inV { get; set; }
public string outV { get; set; }
public TagSenderProperties properties { get; set; }
}
public class TagSenderProperties
{
public int sent { get; set; }
}
}

Двоичные данные
CELA-Tag_Hive_Data_Processing/Program.cs Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("GremlinNetSample")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("GremlinNetSample.Properties")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("9c5203da-7f12-4f74-a5e2-220cb9c79aa2")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,107 @@
function GetDeployment($requestedConfiguration, $configurations)
{
#Iterate over the loaded configurations
foreach ($configuration in $configurations.psobject.Properties)
{
#Return the configuration that matches the request
if ($requestedConfiguration -eq $configuration.Value.ConfigurationDeploymentType)
{
return $configuration.Value
}
}
$error = [string]::Concat('Could not find configuration of type "', $requestedConfiguration,'"')
Write-Error $error
return $null
}
function ProcessStringReplacementsIntoFiles($files, $currentDeployment, $requestedDeployment, $verbose = $false)
{
#Set the filepath tokens to be excluded
$filepathExclusions = @('CELA-Tag_Parsing_Service_Configuration_Utilities','.git','.vs','\bin','\obj','CELA_Tag_Services_Deployment_Configurations.json','CELA-Tagulous_Parsing_Service-Utils.ps1', 'HomeController.cs', 'TestRequest', 'TestEmails')
$configurationPropertyTypeExclusions = @('ConfigurationDeploymentType','ConfigurationDeploymentTypeDescription')
foreach ($file in $files)
{
if ($verbose)
{
[string]::Concat('Processing ', $file.PSPath,'.')
}
#Do not process files that should be excluded
if ($null -eq ($filepathExclusions | ? { $file.PSPath -match [Regex]::Escape($_) }))
{
#[string]::Concat('Would change ', $file.PSPath,'.')
$content = Get-Content $file.PSPath
#Only process files that have content
if (![string]::IsNullOrEmpty($content))
{
$fileUpdatesAvailable = $false
#Iterate over each property in the deployment descriptors
foreach ($property in $currentDeployment.psobject.Properties)
{
#Skip the properties that are metadata, and not values to be replaced
if ($null -eq ($configurationPropertyTypeExclusions | ? { $property.Name -match $_ }))
{
#Get the old property values (to find) and new property values (to be replaced)
$oldValue = $currentDeployment | Select -ExpandProperty $property.Name
$newValue = $requestedDeployment | Select -ExpandProperty $property.Name
$match = $content -match [Regex]::Escape($oldValue)
if (![string]::IsNullOrEmpty($match))
{
if ($verbose)
{
[string]::Concat("`tFrom: ", $oldValue)
[string]::Concat("`tTo: ", $newValue)
[string]::Concat("`tContext: ",$match)
''
}
$content = $content.replace($oldValue, $newValue)
$fileUpdatesAvailable = $true
}
}
}
#Only update the file if changes are available
if ($fileUpdatesAvailable)
{
[string]::Concat("Updating file: ", $file.PSPath)
$content | Out-File -filepath $file.PSPath
}
}
}
}
}
$fileTypesToUpdate = @('*.bot','*.config','*.cs','*.json','*.resx')
'Welcome to CELA Tagulous Parsing Service Utilities.'
[string]::Concat('This application will update the files of type ', $fileTypesToUpdate,' for the specified deployment type.')
#Note that you must customize your own copy of CELA_Tag_Services_Deployment_Configurations_(template).json
$deploymentConfigurationFileName = 'CELA_Tag_Services_Deployment_Configurations.json'
$deploymentConfigurationFileNameDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path
$deploymentConfigurationSearchDirectory = Split-Path -Path $deploymentConfigurationFileNameDirectory -Parent
$deploymentConfigurationFilePath = Join-Path $deploymentConfigurationFileNameDirectory $deploymentConfigurationFileName
$deploymentConfigurations = Get-Content $deploymentConfigurationFilePath | ConvertFrom-Json
'Loaded configurations include:'
"`tType`tDescription"
foreach ($property in $deploymentConfigurations.psobject.Properties)
{
[string]::Concat("`t",$property.Value.ConfigurationDeploymentType, "`t", $property.Value.ConfigurationDeploymentTypeDescription)
}
$deploymentConfigurationTypeCurrent = Read-Host -Prompt 'Please enter the current configuration type of your project (current state)'
$deploymentConfigurationTypeRequested = Read-Host -Prompt 'Please enter the configuration type you want to apply to your project (desired future state)'
$deploymentConfigurationCurrent = GetDeployment $deploymentConfigurationTypeCurrent $deploymentConfigurations
$deploymentConfigurationRequested = GetDeployment $deploymentConfigurationTypeRequested $deploymentConfigurations
if ($deploymentConfigurationCurrent -ne $null -and $deploymentConfigurationRequested -ne $null)
{
$files = Get-ChildItem -Path $deploymentConfigurationSearchDirectory -Recurse -Include $fileTypesToUpdate
ProcessStringReplacementsIntoFiles $files $deploymentConfigurationCurrent $deploymentConfigurationRequested
}
Write-Warning 'You should clean your solution after running this script.'

Просмотреть файл

@ -0,0 +1,37 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>6CAFC0C6-A428-4d30-A9F9-700E829FEA51</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>MyApplication</RootNamespace>
<AssemblyName>MyApplication</AssemblyName>
<Name>CELA-Tag_Parsing_Service_Configuration_Utilities</Name>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Content Include="CELA_Tag_Services_Deployment_Configurations_%28template%29.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="CELA-Tag_Parsing_Service_Configuration_Utilities.ps1" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Target Name="Build" />
<Import Project="$(MSBuildExtensionsPath)\PowerShell Tools for Visual Studio\PowerShellTools.targets" Condition="Exists('$(MSBuildExtensionsPath)\PowerShell Tools for Visual Studio\PowerShellTools.targets')" />
</Project>

Просмотреть файл

@ -0,0 +1,86 @@
{
"NoneConfiguration": {
"ConfigurationDeploymentType": "none",
"ConfigurationDeploymentTypeDescription": "Configures the build to point to replacement tokens for future replacement with other configurations.",
"BotAppPassword": "[BOT_APP_PASSWORD]",
"BotSecret": "[BOT_SECRET]",
"BotFileSecret": "[BOT_SECRET]",
"BotLUISServiceIdentifier": "tagulous-luis",
"BotLUISAppID": "[BOT_LUIS_APP_ID]",
"BotLUISAuthoringKey": "[BOT_LUIS_AUTHORING_KEY]",
"BotLUISSubscriptionKey": "[BOT_LUIS_SUBSCRIPTION_KEY]",
"GraphDatabaseHostname": "[GRAPH_HOSTNAME]",
"GraphDatabasePort": 443,
"GraphDatabaseName": "[GRAPH_NAME]",
"GraphDatabaseCollection": "[GRAPH_COLLECTION]",
"GraphDatabaseAuthorizationKey": "[GRAPH_KEY]",
"TableHostname": "[TABLE_HOSTNAME]",
"TableName": "[TABLE_NAME]",
"TableAccessKey": "[TABLE_KEY]"
},
"ProdConfiguration": {
"ConfigurationDeploymentType": "prod",
"ConfigurationDeploymentTypeDescription": "Configures the build to point to production resources.",
"BotAppPassword": "[BOT_APP_PASSWORD]",
"BotSecret": "[BOT_SECRET]",
"BotFileSecret": "[BOT_SECRET]",
"BotLUISServiceIdentifier": "tagulous-luis",
"BotLUISAppID": "[BOT_LUIS_APP_ID]",
"BotLUISAuthoringKey": "[BOT_LUIS_AUTHORING_KEY]",
"BotLUISSubscriptionKey": "[BOT_LUIS_SUBSCRIPTION_KEY]",
"GraphDatabaseHostname": "tagulous.gremlin.cosmosdb.azure.com",
"GraphDatabasePort": 443,
"GraphDatabaseName": "tagulous-database",
"GraphDatabaseCollection": "tagulous-graph",
"GraphDatabaseAuthorizationKey": "[GRAPH_KEY]",
"TableHostname": "tagulous",
"TableName": "tagulous",
"TableAccessKey": "[TABLE_KEY]"
},
"TestConfiguration": {
"ConfigurationDeploymentType": "test",
"ConfigurationDeploymentTypeDescription": "Configures the build to point to testing resources.",
"GraphDatabaseHostname": "taguloustest.gremlin.cosmosdb.azure.com",
"GraphDatabasePort": 443,
"GraphDatabaseName": "tagulous-database",
"GraphDatabaseCollection": "tagulous-graph",
"GraphDatabaseAuthorizationKey": "[GRAPH_KEY]",
"TableHostname": "taguloustest",
"TableName": "tagulous",
"TableAccessKey": "[TABLE_KEY]",
"BotSecret": "[BOT_SECRET]",
"BotLUISServiceIdentifier": "tagulous-luis",
"BotLUISAppID": "[BOT_LUIS_APP_ID]",
"BotLUISAuthoringKey": "[BOT_LUIS_AUTHORING_KEY]",
"BotLUISSubscriptionKey": "[BOT_LUIS_SUBSCRIPTION_KEY]"
},
"DemoConfiguration": {
"ConfigurationDeploymentType": "demo",
"ConfigurationDeploymentTypeDescription": "Configures the build to point to demonstration resources.",
"BotAppPassword": "[BOT_APP_PASSWORD]",
"BotSecret": "[BOT_SECRET]",
"BotFileSecret": "[BOT_SECRET]",
"BotLUISServiceIdentifier": "tagulous-luis",
"BotLUISAppID": "[BOT_LUIS_APP_ID]",
"BotLUISAuthoringKey": "[BOT_LUIS_AUTHORING_KEY]",
"BotLUISSubscriptionKey": "[BOT_LUIS_SUBSCRIPTION_KEY]",
"GraphDatabaseHostname": "tagulousdemo.gremlin.cosmosdb.azure.com",
"GraphDatabasePort": 443,
"GraphDatabaseName": "tagulous-database",
"GraphDatabaseCollection": "tagulous-graph",
"GraphDatabaseAuthorizationKey": "[GRAPH_KEY]",
"TableHostname": "tagulousdemo",
"TableName": "tagulous",
"TableAccessKey": "[TABLE_KEY]",
},
"BotLocalConfiguration": {
"ConfigurationDeploymentType": "botl",
"ConfigurationDeploymentTypeDescription": "Configures the build for local bot deployment for testing.",
"BotServiceEndpoint": "http://localhost/api/messages"
},
"BotRemoteConfiguration": {
"ConfigurationDeploymentType": "botr",
"ConfigurationDeploymentTypeDescription": "Configures the build for remote bot deployment for production and remote testing.",
"BotServiceEndpoint": "http://[UPDATETHIS].azurewebsites.net/api/messages"
}
}

Просмотреть файл

@ -0,0 +1,28 @@
using System.Web;
using System.Web.Optimization;
namespace CELA_Tags_Parsing_Service
{
public class BundleConfig
{
// For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at https://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
}
}
}

Просмотреть файл

@ -0,0 +1,13 @@
using System.Web;
using System.Web.Mvc;
namespace CELA_Tags_Parsing_Service
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new ErrorHandler.AiHandleErrorAttribute());
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace CELA_Tags_Parsing_Service
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}

Просмотреть файл

@ -0,0 +1,255 @@
using System.Web.Http;
using WebActivatorEx;
using CELA_Tags_Parsing_Service;
using Swashbuckle.Application;
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
namespace CELA_Tags_Parsing_Service
{
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
// By default, the service root url is inferred from the request used to access the docs.
// However, there may be situations (e.g. proxy and load-balanced environments) where this does not
// resolve correctly. You can workaround this by providing your own code to determine the root URL.
//
//c.RootUrl(req => GetRootUrlFromAppConfig());
// If schemes are not explicitly provided in a Swagger 2.0 document, then the scheme used to access
// the docs is taken as the default. If your API supports multiple schemes and you want to be explicit
// about them, you can use the "Schemes" option as shown below.
//
//c.Schemes(new[] { "http", "https" });
// Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to
// hold additional metadata for an API. Version and title are required but you can also provide
// additional fields by chaining methods off SingleApiVersion.
//
c.SingleApiVersion("v1", "CELA_Tags_Parsing_Service");
// If you want the output Swagger docs to be indented properly, enable the "PrettyPrint" option.
//
//c.PrettyPrint();
// If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
// In this case, you must provide a lambda that tells Swashbuckle which actions should be
// included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
// returns an "Info" builder so you can provide additional metadata per API version.
//
//c.MultipleApiVersions(
// (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
// (vc) =>
// {
// vc.Version("v2", "Swashbuckle Dummy API V2");
// vc.Version("v1", "Swashbuckle Dummy API V1");
// });
// You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
// See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
// NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
// at the document or operation level to indicate which schemes are required for an operation. To do this,
// you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
// according to your specific authorization implementation
//
//c.BasicAuth("basic")
// .Description("Basic HTTP Authentication");
//
// NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
//c.ApiKey("apiKey")
// .Description("API Key Authentication")
// .Name("apiKey")
// .In("header");
//
//c.OAuth2("oauth2")
// .Description("OAuth2 Implicit Grant")
// .Flow("implicit")
// .AuthorizationUrl("http://petstore.swagger.wordnik.com/api/oauth/dialog")
// //.TokenUrl("https://tempuri.org/token")
// .Scopes(scopes =>
// {
// scopes.Add("read", "Read access to protected resources");
// scopes.Add("write", "Write access to protected resources");
// });
// Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
//c.IgnoreObsoleteActions();
// Each operation be assigned one or more tags which are then used by consumers for various reasons.
// For example, the swagger-ui groups operations according to the first tag of each operation.
// By default, this will be controller name but you can use the "GroupActionsBy" option to
// override with any value.
//
//c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
// You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
// the order in which operations are listed. For example, if the default grouping is in place
// (controller name) and you specify a descending alphabetic sort order, then actions from a
// ProductsController will be listed before those from a CustomersController. This is typically
// used to customize the order of groupings in the swagger-ui.
//
//c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
// If you annotate Controllers and API Types with
// Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
// those comments into the generated docs and UI. You can enable this by providing the path to one or
// more Xml comment files.
//
c.IncludeXmlComments(string.Format(@"{0}\bin\CELA-Tags_Parsing_Service.xml", System.AppDomain.CurrentDomain.BaseDirectory));
// Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
// exposed in your API. However, there may be occasions when more control of the output is needed.
// This is supported through the "MapType" and "SchemaFilter" options:
//
// Use the "MapType" option to override the Schema generation for a specific type.
// It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
// While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
// It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
// use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
// complex Schema, use a Schema filter.
//
//c.MapType<ProductType>(() => new Schema { type = "integer", format = "int32" });
// If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
// specific type, you can wire up one or more Schema filters.
//
//c.SchemaFilter<ApplySchemaVendorExtensions>();
// In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
// Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
// works well because it prevents the "implementation detail" of type namespaces from leaking into your
// Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
// need to opt out of this behavior to avoid Schema Id conflicts.
//
//c.UseFullTypeNameInSchemaIds();
// Alternatively, you can provide your own custom strategy for inferring SchemaId's for
// describing "complex" types in your API.
//
//c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName);
// Set this flag to omit schema property descriptions for any type properties decorated with the
// Obsolete attribute
//c.IgnoreObsoleteProperties();
// In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
// You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
// enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
// approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
//
//c.DescribeAllEnumsAsStrings();
// Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
//
// Post-modify Operation descriptions once they've been generated by wiring up one or more
// Operation filters.
//
//c.OperationFilter<AddDefaultResponse>();
//
// If you've defined an OAuth2 flow as described above, you could use a custom filter
// to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
// to execute the operation
//
//c.OperationFilter<AssignOAuth2SecurityRequirements>();
// Post-modify the entire Swagger document by wiring up one or more Document filters.
// This gives full control to modify the final SwaggerDocument. You should have a good understanding of
// the Swagger 2.0 spec. - https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md
// before using this option.
//
//c.DocumentFilter<ApplyDocumentVendorExtensions>();
// In contrast to WebApi, Swagger 2.0 does not include the query string component when mapping a URL
// to an action. As a result, Swashbuckle will raise an exception if it encounters multiple actions
// with the same path (sans query string) and HTTP method. You can workaround this by providing a
// custom strategy to pick a winner or merge the descriptions for the purposes of the Swagger docs
//
//c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
// Wrap the default SwaggerGenerator with additional behavior (e.g. caching) or provide an
// alternative implementation for ISwaggerProvider with the CustomProvider option.
//
//c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
})
.EnableSwaggerUi(c =>
{
// Use the "DocumentTitle" option to change the Document title.
// Very helpful when you have multiple Swagger pages open, to tell them apart.
//
//c.DocumentTitle("My Swagger UI");
// Use the "InjectStylesheet" option to enrich the UI with one or more additional CSS stylesheets.
// The file must be included in your project as an "Embedded Resource", and then the resource's
// "Logical Name" is passed to the method as shown below.
//
//c.InjectStylesheet(containingAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");
// Use the "InjectJavaScript" option to invoke one or more custom JavaScripts after the swagger-ui
// has loaded. The file must be included in your project as an "Embedded Resource", and then the resource's
// "Logical Name" is passed to the method as shown above.
//
//c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");
// The swagger-ui renders boolean data types as a dropdown. By default, it provides "true" and "false"
// strings as the possible choices. You can use this option to change these to something else,
// for example 0 and 1.
//
//c.BooleanValues(new[] { "0", "1" });
// By default, swagger-ui will validate specs against swagger.io's online validator and display the result
// in a badge at the bottom of the page. Use these options to set a different validator URL or to disable the
// feature entirely.
//c.SetValidatorUrl("http://localhost/validator");
//c.DisableValidator();
// Use this option to control how the Operation listing is displayed.
// It can be set to "None" (default), "List" (shows operations for each resource),
// or "Full" (fully expanded: shows operations and their details).
//
//c.DocExpansion(DocExpansion.List);
// Specify which HTTP operations will have the 'Try it out!' option. An empty paramter list disables
// it for all operations.
//
//c.SupportedSubmitMethods("GET", "HEAD");
// Use the CustomAsset option to provide your own version of assets used in the swagger-ui.
// It's typically used to instruct Swashbuckle to return your version instead of the default
// when a request is made for "index.html". As with all custom content, the file must be included
// in your project as an "Embedded Resource", and then the resource's "Logical Name" is passed to
// the method as shown below.
//
//c.CustomAsset("index", containingAssembly, "YourWebApiProject.SwaggerExtensions.index.html");
// If your API has multiple versions and you've applied the MultipleApiVersions setting
// as described above, you can also enable a select box in the swagger-ui, that displays
// a discovery URL for each version. This provides a convenient way for users to browse documentation
// for different API versions.
//
//c.EnableDiscoveryUrlSelector();
// If your API supports the OAuth2 Implicit flow, and you've described it correctly, according to
// the Swagger 2.0 specification, you can enable UI support as shown below.
//
//c.EnableOAuth2Support(
// clientId: "test-client-id",
// clientSecret: null,
// realm: "test-realm",
// appName: "Swagger UI"
// //additionalQueryStringParams: new Dictionary<string, string>() { { "foo", "bar" } }
//);
// If your API supports ApiKey, you can override the default values.
// "apiKeyIn" can either be "query" or "header"
//
//c.EnableApiKeySupport("apiKey", "header");
});
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace CELA_Tags_Parsing_Service
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
//See https://stackoverflow.com/questions/44920319/the-request-entitys-media-type-text-plain-is-not-supported-for-this-resource for explanation
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/plain"));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}

Просмотреть файл

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
<InstrumentationKey>56916d08-a5e4-463b-9acc-c0d75d1b18c3</InstrumentationKey>
<TelemetryInitializers>
<Add Type="Microsoft.ApplicationInsights.DependencyCollector.HttpDependenciesParsingTelemetryInitializer, Microsoft.AI.DependencyCollector"/>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.AzureRoleEnvironmentTelemetryInitializer, Microsoft.AI.WindowsServer"/>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.AzureWebAppRoleEnvironmentTelemetryInitializer, Microsoft.AI.WindowsServer"/>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.BuildInfoConfigComponentVersionTelemetryInitializer, Microsoft.AI.WindowsServer"/>
<Add Type="Microsoft.ApplicationInsights.Web.WebTestTelemetryInitializer, Microsoft.AI.Web"/>
<Add Type="Microsoft.ApplicationInsights.Web.SyntheticUserAgentTelemetryInitializer, Microsoft.AI.Web">
<!-- Extended list of bots:
search|spider|crawl|Bot|Monitor|BrowserMob|BingPreview|PagePeeker|WebThumb|URL2PNG|ZooShot|GomezA|Google SketchUp|Read Later|KTXN|KHTE|Keynote|Pingdom|AlwaysOn|zao|borg|oegp|silk|Xenu|zeal|NING|htdig|lycos|slurp|teoma|voila|yahoo|Sogou|CiBra|Nutch|Java|JNLP|Daumoa|Genieo|ichiro|larbin|pompos|Scrapy|snappy|speedy|vortex|favicon|indexer|Riddler|scooter|scraper|scrubby|WhatWeb|WinHTTP|voyager|archiver|Icarus6j|mogimogi|Netvibes|altavista|charlotte|findlinks|Retreiver|TLSProber|WordPress|wsr-agent|http client|Python-urllib|AppEngine-Google|semanticdiscovery|facebookexternalhit|web/snippet|Google-HTTP-Java-Client-->
<Filters>search|spider|crawl|Bot|Monitor|AlwaysOn</Filters>
</Add>
<Add Type="Microsoft.ApplicationInsights.Web.ClientIpHeaderTelemetryInitializer, Microsoft.AI.Web"/>
<Add Type="Microsoft.ApplicationInsights.Web.OperationNameTelemetryInitializer, Microsoft.AI.Web"/>
<Add Type="Microsoft.ApplicationInsights.Web.OperationCorrelationTelemetryInitializer, Microsoft.AI.Web"/>
<Add Type="Microsoft.ApplicationInsights.Web.UserTelemetryInitializer, Microsoft.AI.Web"/>
<Add Type="Microsoft.ApplicationInsights.Web.AuthenticatedUserIdTelemetryInitializer, Microsoft.AI.Web"/>
<Add Type="Microsoft.ApplicationInsights.Web.AccountIdTelemetryInitializer, Microsoft.AI.Web"/>
<Add Type="Microsoft.ApplicationInsights.Web.SessionTelemetryInitializer, Microsoft.AI.Web"/>
</TelemetryInitializers>
<TelemetryModules>
<Add Type="Microsoft.ApplicationInsights.DependencyCollector.DependencyTrackingTelemetryModule, Microsoft.AI.DependencyCollector">
<ExcludeComponentCorrelationHttpHeadersOnDomains>
<!--
Requests to the following hostnames will not be modified by adding correlation headers.
Add entries here to exclude additional hostnames.
NOTE: this configuration will be lost upon NuGet upgrade.
-->
<Add>core.windows.net</Add>
<Add>core.chinacloudapi.cn</Add>
<Add>core.cloudapi.de</Add>
<Add>core.usgovcloudapi.net</Add>
<Add>localhost</Add>
<Add>127.0.0.1</Add>
</ExcludeComponentCorrelationHttpHeadersOnDomains>
<IncludeDiagnosticSourceActivities>
<Add>Microsoft.Azure.EventHubs</Add>
<Add>Microsoft.Azure.ServiceBus</Add>
</IncludeDiagnosticSourceActivities>
</Add>
<Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.PerformanceCollectorModule, Microsoft.AI.PerfCounterCollector">
<!--
Use the following syntax here to collect additional performance counters:
<Counters>
<Add PerformanceCounter="\Process(??APP_WIN32_PROC??)\Handle Count" ReportAs="Process handle count" />
...
</Counters>
PerformanceCounter must be either \CategoryName(InstanceName)\CounterName or \CategoryName\CounterName
NOTE: performance counters configuration will be lost upon NuGet upgrade.
The following placeholders are supported as InstanceName:
??APP_WIN32_PROC?? - instance name of the application process for Win32 counters.
??APP_W3SVC_PROC?? - instance name of the application IIS worker process for IIS/ASP.NET counters.
??APP_CLR_PROC?? - instance name of the application CLR process for .NET counters.
-->
</Add>
<Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse.QuickPulseTelemetryModule, Microsoft.AI.PerfCounterCollector"/>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.AppServicesHeartbeatTelemetryModule, Microsoft.AI.WindowsServer"/>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.AzureInstanceMetadataTelemetryModule, Microsoft.AI.WindowsServer">
<!--
Remove individual fields collected here by adding them to the ApplicationInsighs.HeartbeatProvider
with the following syntax:
<Add Type="Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.DiagnosticsTelemetryModule, Microsoft.ApplicationInsights">
<ExcludedHeartbeatProperties>
<Add>osType</Add>
<Add>location</Add>
<Add>name</Add>
<Add>offer</Add>
<Add>platformFaultDomain</Add>
<Add>platformUpdateDomain</Add>
<Add>publisher</Add>
<Add>sku</Add>
<Add>version</Add>
<Add>vmId</Add>
<Add>vmSize</Add>
<Add>subscriptionId</Add>
<Add>resourceGroupName</Add>
<Add>placementGroupId</Add>
<Add>tags</Add>
<Add>vmScaleSetName</Add>
</ExcludedHeartbeatProperties>
</Add>
NOTE: exclusions will be lost upon upgrade.
-->
</Add>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.DeveloperModeWithDebuggerAttachedTelemetryModule, Microsoft.AI.WindowsServer"/>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.UnhandledExceptionTelemetryModule, Microsoft.AI.WindowsServer"/>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.UnobservedExceptionTelemetryModule, Microsoft.AI.WindowsServer">
<!--</Add>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.FirstChanceExceptionStatisticsTelemetryModule, Microsoft.AI.WindowsServer">-->
</Add>
<Add Type="Microsoft.ApplicationInsights.Web.RequestTrackingTelemetryModule, Microsoft.AI.Web">
<Handlers>
<!--
Add entries here to filter out additional handlers:
NOTE: handler configuration will be lost upon NuGet upgrade.
-->
<Add>Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.RequestDataHttpHandler</Add>
<Add>System.Web.StaticFileHandler</Add>
<Add>System.Web.Handlers.AssemblyResourceLoader</Add>
<Add>System.Web.Optimization.BundleHandler</Add>
<Add>System.Web.Script.Services.ScriptHandlerFactory</Add>
<Add>System.Web.Handlers.TraceHandler</Add>
<Add>System.Web.Services.Discovery.DiscoveryRequestHandler</Add>
<Add>System.Web.HttpDebugHandler</Add>
</Handlers>
</Add>
<Add Type="Microsoft.ApplicationInsights.Web.ExceptionTrackingTelemetryModule, Microsoft.AI.Web"/>
<Add Type="Microsoft.ApplicationInsights.Web.AspNetDiagnosticTelemetryModule, Microsoft.AI.Web"/>
</TelemetryModules>
<ApplicationIdProvider Type="Microsoft.ApplicationInsights.Extensibility.Implementation.ApplicationId.ApplicationInsightsApplicationIdProvider, Microsoft.ApplicationInsights"/>
<TelemetrySinks>
<Add Name="default">
<TelemetryProcessors>
<Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse.QuickPulseTelemetryProcessor, Microsoft.AI.PerfCounterCollector"/>
<Add Type="Microsoft.ApplicationInsights.Extensibility.AutocollectedMetricsExtractor, Microsoft.ApplicationInsights"/>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.AdaptiveSamplingTelemetryProcessor, Microsoft.AI.ServerTelemetryChannel">
<MaxTelemetryItemsPerSecond>5</MaxTelemetryItemsPerSecond>
<ExcludedTypes>Event</ExcludedTypes>
</Add>
<Add Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.AdaptiveSamplingTelemetryProcessor, Microsoft.AI.ServerTelemetryChannel">
<MaxTelemetryItemsPerSecond>5</MaxTelemetryItemsPerSecond>
<IncludedTypes>Event</IncludedTypes>
</Add>
</TelemetryProcessors>
<TelemetryChannel Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel, Microsoft.AI.ServerTelemetryChannel"/>
</Add>
</TelemetrySinks>
<!--
Learn more about Application Insights configuration with ApplicationInsights.config here:
http://go.microsoft.com/fwlink/?LinkID=513840
Note: If not present, please add <InstrumentationKey>Your Key</InstrumentationKey> to the top of this file.
--></ApplicationInsights>

Просмотреть файл

@ -0,0 +1,39 @@
using System;
using System.Text;
using System.Web;
using System.Web.Http.Description;
namespace CELA_Tags_Parsing_Service.Areas.HelpPage
{
public static class ApiDescriptionExtensions
{
/// <summary>
/// Generates an URI-friendly ID for the <see cref="ApiDescription"/>. E.g. "Get-Values-id_name" instead of "GetValues/{id}?name={name}"
/// </summary>
/// <param name="description">The <see cref="ApiDescription"/>.</param>
/// <returns>The ID as a string.</returns>
public static string GetFriendlyId(this ApiDescription description)
{
string path = description.RelativePath;
string[] urlParts = path.Split('?');
string localPath = urlParts[0];
string queryKeyString = null;
if (urlParts.Length > 1)
{
string query = urlParts[1];
string[] queryKeys = HttpUtility.ParseQueryString(query).AllKeys;
queryKeyString = String.Join("_", queryKeys);
}
StringBuilder friendlyPath = new StringBuilder();
friendlyPath.AppendFormat("{0}-{1}",
description.HttpMethod.Method,
localPath.Replace("/", "-").Replace("{", String.Empty).Replace("}", String.Empty));
if (queryKeyString != null)
{
friendlyPath.AppendFormat("_{0}", queryKeyString.Replace('.', '-'));
}
return friendlyPath.ToString();
}
}
}

Просмотреть файл

@ -0,0 +1,113 @@
// Uncomment the following to provide samples for PageResult<T>. Must also add the Microsoft.AspNet.WebApi.OData
// package to your project.
////#define Handle_PageResultOfT
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http.Headers;
using System.Reflection;
using System.Web;
using System.Web.Http;
#if Handle_PageResultOfT
using System.Web.Http.OData;
#endif
namespace CELA_Tags_Parsing_Service.Areas.HelpPage
{
/// <summary>
/// Use this class to customize the Help Page.
/// For example you can set a custom <see cref="System.Web.Http.Description.IDocumentationProvider"/> to supply the documentation
/// or you can provide the samples for the requests/responses.
/// </summary>
public static class HelpPageConfig
{
[SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters",
MessageId = "CELA_Tags_Parsing_Service.Areas.HelpPage.TextSample.#ctor(System.String)",
Justification = "End users may choose to merge this string with existing localized resources.")]
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly",
MessageId = "bsonspec",
Justification = "Part of a URI.")]
public static void Register(HttpConfiguration config)
{
//// Uncomment the following to use the documentation from XML documentation file.
//config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));
//// Uncomment the following to use "sample string" as the sample for all actions that have string as the body parameter or return type.
//// Also, the string arrays will be used for IEnumerable<string>. The sample objects will be serialized into different media type
//// formats by the available formatters.
//config.SetSampleObjects(new Dictionary<Type, object>
//{
// {typeof(string), "sample string"},
// {typeof(IEnumerable<string>), new string[]{"sample 1", "sample 2"}}
//});
// Extend the following to provide factories for types not handled automatically (those lacking parameterless
// constructors) or for which you prefer to use non-default property values. Line below provides a fallback
// since automatic handling will fail and GeneratePageResult handles only a single type.
#if Handle_PageResultOfT
config.GetHelpPageSampleGenerator().SampleObjectFactories.Add(GeneratePageResult);
#endif
// Extend the following to use a preset object directly as the sample for all actions that support a media
// type, regardless of the body parameter or return type. The lines below avoid display of binary content.
// The BsonMediaTypeFormatter (if available) is not used to serialize the TextSample object.
config.SetSampleForMediaType(
new TextSample("Binary JSON content. See http://bsonspec.org for details."),
new MediaTypeHeaderValue("application/bson"));
//// Uncomment the following to use "[0]=foo&[1]=bar" directly as the sample for all actions that support form URL encoded format
//// and have IEnumerable<string> as the body parameter or return type.
//config.SetSampleForType("[0]=foo&[1]=bar", new MediaTypeHeaderValue("application/x-www-form-urlencoded"), typeof(IEnumerable<string>));
//// Uncomment the following to use "1234" directly as the request sample for media type "text/plain" on the controller named "Values"
//// and action named "Put".
//config.SetSampleRequest("1234", new MediaTypeHeaderValue("text/plain"), "Values", "Put");
//// Uncomment the following to use the image on "../images/aspNetHome.png" directly as the response sample for media type "image/png"
//// on the controller named "Values" and action named "Get" with parameter "id".
//config.SetSampleResponse(new ImageSample("../images/aspNetHome.png"), new MediaTypeHeaderValue("image/png"), "Values", "Get", "id");
//// Uncomment the following to correct the sample request when the action expects an HttpRequestMessage with ObjectContent<string>.
//// The sample will be generated as if the controller named "Values" and action named "Get" were having string as the body parameter.
//config.SetActualRequestType(typeof(string), "Values", "Get");
//// Uncomment the following to correct the sample response when the action returns an HttpResponseMessage with ObjectContent<string>.
//// The sample will be generated as if the controller named "Values" and action named "Post" were returning a string.
//config.SetActualResponseType(typeof(string), "Values", "Post");
}
#if Handle_PageResultOfT
private static object GeneratePageResult(HelpPageSampleGenerator sampleGenerator, Type type)
{
if (type.IsGenericType)
{
Type openGenericType = type.GetGenericTypeDefinition();
if (openGenericType == typeof(PageResult<>))
{
// Get the T in PageResult<T>
Type[] typeParameters = type.GetGenericArguments();
Debug.Assert(typeParameters.Length == 1);
// Create an enumeration to pass as the first parameter to the PageResult<T> constuctor
Type itemsType = typeof(List<>).MakeGenericType(typeParameters);
object items = sampleGenerator.GetSampleObject(itemsType);
// Fill in the other information needed to invoke the PageResult<T> constuctor
Type[] parameterTypes = new Type[] { itemsType, typeof(Uri), typeof(long?), };
object[] parameters = new object[] { items, null, (long)ObjectGenerator.DefaultCollectionSize, };
// Call PageResult(IEnumerable<T> items, Uri nextPageLink, long? count) constructor
ConstructorInfo constructor = type.GetConstructor(parameterTypes);
return constructor.Invoke(parameters);
}
}
return null;
}
#endif
}
}

Просмотреть файл

@ -0,0 +1,63 @@
using System;
using System.Web.Http;
using System.Web.Mvc;
using CELA_Tags_Parsing_Service.Areas.HelpPage.ModelDescriptions;
using CELA_Tags_Parsing_Service.Areas.HelpPage.Models;
namespace CELA_Tags_Parsing_Service.Areas.HelpPage.Controllers
{
/// <summary>
/// The controller that will handle requests for the help page.
/// </summary>
public class HelpController : Controller
{
private const string ErrorViewName = "Error";
public HelpController()
: this(GlobalConfiguration.Configuration)
{
}
public HelpController(HttpConfiguration config)
{
Configuration = config;
}
public HttpConfiguration Configuration { get; private set; }
public ActionResult Index()
{
ViewBag.DocumentationProvider = Configuration.Services.GetDocumentationProvider();
return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
}
public ActionResult Api(string apiId)
{
if (!String.IsNullOrEmpty(apiId))
{
HelpPageApiModel apiModel = Configuration.GetHelpPageApiModel(apiId);
if (apiModel != null)
{
return View(apiModel);
}
}
return View(ErrorViewName);
}
public ActionResult ResourceModel(string modelName)
{
if (!String.IsNullOrEmpty(modelName))
{
ModelDescriptionGenerator modelDescriptionGenerator = Configuration.GetModelDescriptionGenerator();
ModelDescription modelDescription;
if (modelDescriptionGenerator.GeneratedModels.TryGetValue(modelName, out modelDescription))
{
return View(modelDescription);
}
}
return View(ErrorViewName);
}
}
}

Просмотреть файл

@ -0,0 +1,134 @@
.help-page h1,
.help-page .h1,
.help-page h2,
.help-page .h2,
.help-page h3,
.help-page .h3,
#body.help-page,
.help-page-table th,
.help-page-table pre,
.help-page-table p {
font-family: "Segoe UI Light", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;
}
.help-page pre.wrapped {
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
white-space: pre-wrap;
}
.help-page .warning-message-container {
margin-top: 20px;
padding: 0 10px;
color: #525252;
background: #EFDCA9;
border: 1px solid #CCCCCC;
}
.help-page-table {
width: 100%;
border-collapse: collapse;
text-align: left;
margin: 0px 0px 20px 0px;
border-top: 1px solid #D4D4D4;
}
.help-page-table th {
text-align: left;
font-weight: bold;
border-bottom: 1px solid #D4D4D4;
padding: 5px 6px 5px 6px;
}
.help-page-table td {
border-bottom: 1px solid #D4D4D4;
padding: 10px 8px 10px 8px;
vertical-align: top;
}
.help-page-table pre,
.help-page-table p {
margin: 0px;
padding: 0px;
font-family: inherit;
font-size: 100%;
}
.help-page-table tbody tr:hover td {
background-color: #F3F3F3;
}
.help-page a:hover {
background-color: transparent;
}
.help-page .sample-header {
border: 2px solid #D4D4D4;
background: #00497E;
color: #FFFFFF;
padding: 8px 15px;
border-bottom: none;
display: inline-block;
margin: 10px 0px 0px 0px;
}
.help-page .sample-content {
display: block;
border-width: 0;
padding: 15px 20px;
background: #FFFFFF;
border: 2px solid #D4D4D4;
margin: 0px 0px 10px 0px;
}
.help-page .api-name {
width: 40%;
}
.help-page .api-documentation {
width: 60%;
}
.help-page .parameter-name {
width: 20%;
}
.help-page .parameter-documentation {
width: 40%;
}
.help-page .parameter-type {
width: 20%;
}
.help-page .parameter-annotations {
width: 20%;
}
.help-page h1,
.help-page .h1 {
font-size: 36px;
line-height: normal;
}
.help-page h2,
.help-page .h2 {
font-size: 24px;
}
.help-page h3,
.help-page .h3 {
font-size: 20px;
}
#body.help-page {
font-size: 14px;
line-height: 143%;
color: #333;
}
.help-page a {
color: #0000EE;
text-decoration: none;
}

Просмотреть файл

@ -0,0 +1,26 @@
using System.Web.Http;
using System.Web.Mvc;
namespace CELA_Tags_Parsing_Service.Areas.HelpPage
{
public class HelpPageAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "HelpPage";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"HelpPage_Default",
"Help/{action}/{apiId}",
new { controller = "Help", action = "Index", apiId = UrlParameter.Optional });
HelpPageConfig.Register(GlobalConfiguration.Configuration);
}
}
}

Просмотреть файл

@ -0,0 +1,467 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Description;
using CELA_Tags_Parsing_Service.Areas.HelpPage.ModelDescriptions;
using CELA_Tags_Parsing_Service.Areas.HelpPage.Models;
namespace CELA_Tags_Parsing_Service.Areas.HelpPage
{
public static class HelpPageConfigurationExtensions
{
private const string ApiModelPrefix = "MS_HelpPageApiModel_";
/// <summary>
/// Sets the documentation provider for help page.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="documentationProvider">The documentation provider.</param>
public static void SetDocumentationProvider(this HttpConfiguration config, IDocumentationProvider documentationProvider)
{
config.Services.Replace(typeof(IDocumentationProvider), documentationProvider);
}
/// <summary>
/// Sets the objects that will be used by the formatters to produce sample requests/responses.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="sampleObjects">The sample objects.</param>
public static void SetSampleObjects(this HttpConfiguration config, IDictionary<Type, object> sampleObjects)
{
config.GetHelpPageSampleGenerator().SampleObjects = sampleObjects;
}
/// <summary>
/// Sets the sample request directly for the specified media type and action.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="sample">The sample request.</param>
/// <param name="mediaType">The media type.</param>
/// <param name="controllerName">Name of the controller.</param>
/// <param name="actionName">Name of the action.</param>
public static void SetSampleRequest(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Request, controllerName, actionName, new[] { "*" }), sample);
}
/// <summary>
/// Sets the sample request directly for the specified media type and action with parameters.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="sample">The sample request.</param>
/// <param name="mediaType">The media type.</param>
/// <param name="controllerName">Name of the controller.</param>
/// <param name="actionName">Name of the action.</param>
/// <param name="parameterNames">The parameter names.</param>
public static void SetSampleRequest(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName, params string[] parameterNames)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Request, controllerName, actionName, parameterNames), sample);
}
/// <summary>
/// Sets the sample request directly for the specified media type of the action.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="sample">The sample response.</param>
/// <param name="mediaType">The media type.</param>
/// <param name="controllerName">Name of the controller.</param>
/// <param name="actionName">Name of the action.</param>
public static void SetSampleResponse(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Response, controllerName, actionName, new[] { "*" }), sample);
}
/// <summary>
/// Sets the sample response directly for the specified media type of the action with specific parameters.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="sample">The sample response.</param>
/// <param name="mediaType">The media type.</param>
/// <param name="controllerName">Name of the controller.</param>
/// <param name="actionName">Name of the action.</param>
/// <param name="parameterNames">The parameter names.</param>
public static void SetSampleResponse(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName, params string[] parameterNames)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Response, controllerName, actionName, parameterNames), sample);
}
/// <summary>
/// Sets the sample directly for all actions with the specified media type.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="sample">The sample.</param>
/// <param name="mediaType">The media type.</param>
public static void SetSampleForMediaType(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType), sample);
}
/// <summary>
/// Sets the sample directly for all actions with the specified type and media type.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="sample">The sample.</param>
/// <param name="mediaType">The media type.</param>
/// <param name="type">The parameter type or return type of an action.</param>
public static void SetSampleForType(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, Type type)
{
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, type), sample);
}
/// <summary>
/// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> passed to the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
/// The help page will use this information to produce more accurate request samples.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="type">The type.</param>
/// <param name="controllerName">Name of the controller.</param>
/// <param name="actionName">Name of the action.</param>
public static void SetActualRequestType(this HttpConfiguration config, Type type, string controllerName, string actionName)
{
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Request, controllerName, actionName, new[] { "*" }), type);
}
/// <summary>
/// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> passed to the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
/// The help page will use this information to produce more accurate request samples.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="type">The type.</param>
/// <param name="controllerName">Name of the controller.</param>
/// <param name="actionName">Name of the action.</param>
/// <param name="parameterNames">The parameter names.</param>
public static void SetActualRequestType(this HttpConfiguration config, Type type, string controllerName, string actionName, params string[] parameterNames)
{
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Request, controllerName, actionName, parameterNames), type);
}
/// <summary>
/// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> returned as part of the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
/// The help page will use this information to produce more accurate response samples.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="type">The type.</param>
/// <param name="controllerName">Name of the controller.</param>
/// <param name="actionName">Name of the action.</param>
public static void SetActualResponseType(this HttpConfiguration config, Type type, string controllerName, string actionName)
{
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Response, controllerName, actionName, new[] { "*" }), type);
}
/// <summary>
/// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> returned as part of the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
/// The help page will use this information to produce more accurate response samples.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="type">The type.</param>
/// <param name="controllerName">Name of the controller.</param>
/// <param name="actionName">Name of the action.</param>
/// <param name="parameterNames">The parameter names.</param>
public static void SetActualResponseType(this HttpConfiguration config, Type type, string controllerName, string actionName, params string[] parameterNames)
{
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Response, controllerName, actionName, parameterNames), type);
}
/// <summary>
/// Gets the help page sample generator.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <returns>The help page sample generator.</returns>
public static HelpPageSampleGenerator GetHelpPageSampleGenerator(this HttpConfiguration config)
{
return (HelpPageSampleGenerator)config.Properties.GetOrAdd(
typeof(HelpPageSampleGenerator),
k => new HelpPageSampleGenerator());
}
/// <summary>
/// Sets the help page sample generator.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="sampleGenerator">The help page sample generator.</param>
public static void SetHelpPageSampleGenerator(this HttpConfiguration config, HelpPageSampleGenerator sampleGenerator)
{
config.Properties.AddOrUpdate(
typeof(HelpPageSampleGenerator),
k => sampleGenerator,
(k, o) => sampleGenerator);
}
/// <summary>
/// Gets the model description generator.
/// </summary>
/// <param name="config">The configuration.</param>
/// <returns>The <see cref="ModelDescriptionGenerator"/></returns>
public static ModelDescriptionGenerator GetModelDescriptionGenerator(this HttpConfiguration config)
{
return (ModelDescriptionGenerator)config.Properties.GetOrAdd(
typeof(ModelDescriptionGenerator),
k => InitializeModelDescriptionGenerator(config));
}
/// <summary>
/// Gets the model that represents an API displayed on the help page. The model is initialized on the first call and cached for subsequent calls.
/// </summary>
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
/// <param name="apiDescriptionId">The <see cref="ApiDescription"/> ID.</param>
/// <returns>
/// An <see cref="HelpPageApiModel"/>
/// </returns>
public static HelpPageApiModel GetHelpPageApiModel(this HttpConfiguration config, string apiDescriptionId)
{
object model;
string modelId = ApiModelPrefix + apiDescriptionId;
if (!config.Properties.TryGetValue(modelId, out model))
{
Collection<ApiDescription> apiDescriptions = config.Services.GetApiExplorer().ApiDescriptions;
ApiDescription apiDescription = apiDescriptions.FirstOrDefault(api => String.Equals(api.GetFriendlyId(), apiDescriptionId, StringComparison.OrdinalIgnoreCase));
if (apiDescription != null)
{
model = GenerateApiModel(apiDescription, config);
config.Properties.TryAdd(modelId, model);
}
}
return (HelpPageApiModel)model;
}
private static HelpPageApiModel GenerateApiModel(ApiDescription apiDescription, HttpConfiguration config)
{
HelpPageApiModel apiModel = new HelpPageApiModel()
{
ApiDescription = apiDescription,
};
ModelDescriptionGenerator modelGenerator = config.GetModelDescriptionGenerator();
HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
GenerateUriParameters(apiModel, modelGenerator);
GenerateRequestModelDescription(apiModel, modelGenerator, sampleGenerator);
GenerateResourceDescription(apiModel, modelGenerator);
GenerateSamples(apiModel, sampleGenerator);
return apiModel;
}
private static void GenerateUriParameters(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator)
{
ApiDescription apiDescription = apiModel.ApiDescription;
foreach (ApiParameterDescription apiParameter in apiDescription.ParameterDescriptions)
{
if (apiParameter.Source == ApiParameterSource.FromUri)
{
HttpParameterDescriptor parameterDescriptor = apiParameter.ParameterDescriptor;
Type parameterType = null;
ModelDescription typeDescription = null;
ComplexTypeModelDescription complexTypeDescription = null;
if (parameterDescriptor != null)
{
parameterType = parameterDescriptor.ParameterType;
typeDescription = modelGenerator.GetOrCreateModelDescription(parameterType);
complexTypeDescription = typeDescription as ComplexTypeModelDescription;
}
// Example:
// [TypeConverter(typeof(PointConverter))]
// public class Point
// {
// public Point(int x, int y)
// {
// X = x;
// Y = y;
// }
// public int X { get; set; }
// public int Y { get; set; }
// }
// Class Point is bindable with a TypeConverter, so Point will be added to UriParameters collection.
//
// public class Point
// {
// public int X { get; set; }
// public int Y { get; set; }
// }
// Regular complex class Point will have properties X and Y added to UriParameters collection.
if (complexTypeDescription != null
&& !IsBindableWithTypeConverter(parameterType))
{
foreach (ParameterDescription uriParameter in complexTypeDescription.Properties)
{
apiModel.UriParameters.Add(uriParameter);
}
}
else if (parameterDescriptor != null)
{
ParameterDescription uriParameter =
AddParameterDescription(apiModel, apiParameter, typeDescription);
if (!parameterDescriptor.IsOptional)
{
uriParameter.Annotations.Add(new ParameterAnnotation() { Documentation = "Required" });
}
object defaultValue = parameterDescriptor.DefaultValue;
if (defaultValue != null)
{
uriParameter.Annotations.Add(new ParameterAnnotation() { Documentation = "Default value is " + Convert.ToString(defaultValue, CultureInfo.InvariantCulture) });
}
}
else
{
Debug.Assert(parameterDescriptor == null);
// If parameterDescriptor is null, this is an undeclared route parameter which only occurs
// when source is FromUri. Ignored in request model and among resource parameters but listed
// as a simple string here.
ModelDescription modelDescription = modelGenerator.GetOrCreateModelDescription(typeof(string));
AddParameterDescription(apiModel, apiParameter, modelDescription);
}
}
}
}
private static bool IsBindableWithTypeConverter(Type parameterType)
{
if (parameterType == null)
{
return false;
}
return TypeDescriptor.GetConverter(parameterType).CanConvertFrom(typeof(string));
}
private static ParameterDescription AddParameterDescription(HelpPageApiModel apiModel,
ApiParameterDescription apiParameter, ModelDescription typeDescription)
{
ParameterDescription parameterDescription = new ParameterDescription
{
Name = apiParameter.Name,
Documentation = apiParameter.Documentation,
TypeDescription = typeDescription,
};
apiModel.UriParameters.Add(parameterDescription);
return parameterDescription;
}
private static void GenerateRequestModelDescription(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator, HelpPageSampleGenerator sampleGenerator)
{
ApiDescription apiDescription = apiModel.ApiDescription;
foreach (ApiParameterDescription apiParameter in apiDescription.ParameterDescriptions)
{
if (apiParameter.Source == ApiParameterSource.FromBody)
{
Type parameterType = apiParameter.ParameterDescriptor.ParameterType;
apiModel.RequestModelDescription = modelGenerator.GetOrCreateModelDescription(parameterType);
apiModel.RequestDocumentation = apiParameter.Documentation;
}
else if (apiParameter.ParameterDescriptor != null &&
apiParameter.ParameterDescriptor.ParameterType == typeof(HttpRequestMessage))
{
Type parameterType = sampleGenerator.ResolveHttpRequestMessageType(apiDescription);
if (parameterType != null)
{
apiModel.RequestModelDescription = modelGenerator.GetOrCreateModelDescription(parameterType);
}
}
}
}
private static void GenerateResourceDescription(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator)
{
ResponseDescription response = apiModel.ApiDescription.ResponseDescription;
Type responseType = response.ResponseType ?? response.DeclaredType;
if (responseType != null && responseType != typeof(void))
{
apiModel.ResourceDescription = modelGenerator.GetOrCreateModelDescription(responseType);
}
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The exception is recorded as ErrorMessages.")]
private static void GenerateSamples(HelpPageApiModel apiModel, HelpPageSampleGenerator sampleGenerator)
{
try
{
foreach (var item in sampleGenerator.GetSampleRequests(apiModel.ApiDescription))
{
apiModel.SampleRequests.Add(item.Key, item.Value);
LogInvalidSampleAsError(apiModel, item.Value);
}
foreach (var item in sampleGenerator.GetSampleResponses(apiModel.ApiDescription))
{
apiModel.SampleResponses.Add(item.Key, item.Value);
LogInvalidSampleAsError(apiModel, item.Value);
}
}
catch (Exception e)
{
apiModel.ErrorMessages.Add(String.Format(CultureInfo.CurrentCulture,
"An exception has occurred while generating the sample. Exception message: {0}",
HelpPageSampleGenerator.UnwrapException(e).Message));
}
}
private static bool TryGetResourceParameter(ApiDescription apiDescription, HttpConfiguration config, out ApiParameterDescription parameterDescription, out Type resourceType)
{
parameterDescription = apiDescription.ParameterDescriptions.FirstOrDefault(
p => p.Source == ApiParameterSource.FromBody ||
(p.ParameterDescriptor != null && p.ParameterDescriptor.ParameterType == typeof(HttpRequestMessage)));
if (parameterDescription == null)
{
resourceType = null;
return false;
}
resourceType = parameterDescription.ParameterDescriptor.ParameterType;
if (resourceType == typeof(HttpRequestMessage))
{
HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
resourceType = sampleGenerator.ResolveHttpRequestMessageType(apiDescription);
}
if (resourceType == null)
{
parameterDescription = null;
return false;
}
return true;
}
private static ModelDescriptionGenerator InitializeModelDescriptionGenerator(HttpConfiguration config)
{
ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);
Collection<ApiDescription> apis = config.Services.GetApiExplorer().ApiDescriptions;
foreach (ApiDescription api in apis)
{
ApiParameterDescription parameterDescription;
Type parameterType;
if (TryGetResourceParameter(api, config, out parameterDescription, out parameterType))
{
modelGenerator.GetOrCreateModelDescription(parameterType);
}
}
return modelGenerator;
}
private static void LogInvalidSampleAsError(HelpPageApiModel apiModel, object sample)
{
InvalidSample invalidSample = sample as InvalidSample;
if (invalidSample != null)
{
apiModel.ErrorMessages.Add(invalidSample.ErrorMessage);
}
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
namespace CELA_Tags_Parsing_Service.Areas.HelpPage.ModelDescriptions
{
public class CollectionModelDescription : ModelDescription
{
public ModelDescription ElementDescription { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,14 @@
using System.Collections.ObjectModel;
namespace CELA_Tags_Parsing_Service.Areas.HelpPage.ModelDescriptions
{
public class ComplexTypeModelDescription : ModelDescription
{
public ComplexTypeModelDescription()
{
Properties = new Collection<ParameterDescription>();
}
public Collection<ParameterDescription> Properties { get; private set; }
}
}

Просмотреть файл

@ -0,0 +1,6 @@
namespace CELA_Tags_Parsing_Service.Areas.HelpPage.ModelDescriptions
{
public class DictionaryModelDescription : KeyValuePairModelDescription
{
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше