├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── Lab Resources
├── Build Managed Solution.json
├── Deploy to Production.json
├── Export From Dev.json
├── Hands-on with Power Apps and Azure.pptx
├── Hands-on with PowerApps and Azure-Lab Document.docx
├── Hands-on with PowerApps and Azure-Lab Document.pdf
├── Product.svg
├── Products_list_icon.jpg
└── Swagger.json
├── README.md
├── SECURITY.md
└── src
├── ProductListAPI.sln
└── ProductListAPI
├── App_Start
├── GenericStorage.cs
├── SwaggerConfig.cs
└── WebApiConfig.cs
├── Controllers
└── ProductsController.cs
├── Global.asax
├── Global.asax.cs
├── Models
└── Product.cs
├── ProductListAPI.csproj
├── ProductListAPI.csproj.user
├── Properties
└── AssemblyInfo.cs
├── Web.Debug.config
├── Web.Release.config
├── Web.config
├── apiapp.json
└── packages.config
/.gitignore:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio.
3 | ################################################################################
4 |
5 | /src/.vs/ProductListAPI
6 | /src/packages
7 | /src/ProductListAPI/bin
8 | /src/ProductListAPI/obj
9 | /src/ProductListAPI/Properties/PublishProfiles
10 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/Lab Resources/Build Managed Solution.json:
--------------------------------------------------------------------------------
1 | {"options":[{"enabled":false,"definition":{"id":"5d58cc01-7c75-450c-be18-a388ddb129ec"},"inputs":{"branchFilters":"[\"+refs/heads/*\"]","additionalFields":"{}"}},{"enabled":false,"definition":{"id":"a9db38f9-9fdc-478c-b0f9-464221e58316"},"inputs":{"workItemType":"Bug","assignToRequestor":"true","additionalFields":"{}"}}],"variables":{"SolutionName":{"value":"AssetManagement"},"system.debug":{"value":"false","allowOverride":true}},"properties":{},"tags":[],"_links":{"self":{"href":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_apis/build/Definitions/7?revision=3"},"web":{"href":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_build/definition?definitionId=7"},"editor":{"href":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_build/designer?id=7&_a=edit-build-definition"},"badge":{"href":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_apis/build/status/7"}},"jobAuthorizationScope":1,"jobTimeoutInMinutes":60,"jobCancelTimeoutInMinutes":5,"process":{"phases":[{"steps":[{"environment":{},"enabled":true,"continueOnError":false,"alwaysRun":false,"displayName":"PowerApps Tool Installer ","timeoutInMinutes":0,"condition":"succeeded()","task":{"id":"20f1587d-7424-466b-9208-baa837bb020f","versionSpec":"0.*","definitionType":"task"},"inputs":{"XrmOnlineManagementApiVersion":"1.1.0.9053","XrmToolingCrmConnectorVersion":"3.3.0.834","XrmToolingPackageDeploymentVersion":"3.3.0.833","MicrosoftPowerAppsCheckerVersion":"1.0.2","CrmSdkCoreToolsVersion":"9.0.3.1"}},{"environment":{},"enabled":true,"continueOnError":false,"alwaysRun":false,"displayName":"PowerApps Pack Solution ","timeoutInMinutes":0,"condition":"succeeded()","task":{"id":"bfde445b-beda-4a1d-8459-a1869f3f63af","versionSpec":"0.*","definitionType":"task"},"inputs":{"SolutionSourceFolder":"CdsConfig","SolutionOutputFile":"$(Build.ArtifactStagingDirectory)\\$(SolutionName).zip","SolutionType":"Unmanaged"}},{"environment":{},"enabled":true,"continueOnError":false,"alwaysRun":false,"displayName":"PowerApps Import Solution ","timeoutInMinutes":0,"condition":"succeeded()","task":{"id":"89fa86fd-4b50-4d77-8c5f-a876e7a3e2dd","versionSpec":"0.*","definitionType":"task"},"inputs":{"PowerAppsEnvironment":"f0570fb5-349f-4762-9eda-35dfccebd127","SolutionInputFile":"$(Build.ArtifactStagingDirectory)\\$(SolutionName).zip","ConvertToManaged":"false","HoldingSolution":"false","OverwriteUnmanagedCustomizations":"false","PublishWorkflows":"false","SkipProductUpdateDependencies":"false","AsyncOperation":"true"}},{"environment":{},"enabled":true,"continueOnError":false,"alwaysRun":false,"displayName":"PowerApps Export Solution ","timeoutInMinutes":0,"condition":"succeeded()","task":{"id":"c8b391bf-3134-4c03-9965-3af46ce54a4d","versionSpec":"0.*","definitionType":"task"},"inputs":{"PowerAppsEnvironment":"f0570fb5-349f-4762-9eda-35dfccebd127","SolutionName":"$(SolutionName)","SolutionOutputFile":"$(Build.ArtifactStagingDirectory)\\$(SolutionName)_managed.zip","Managed":"true","ExportAutoNumberingSettings":"false","ExportCalendarSettings":"false","ExportCustomizationSettings":"false","ExportEmailTrackingSettings":"false","ExportGeneralSettings":"false","ExportIsvConfig":"false","ExportMarketingSettings":"false","ExportOutlookSynchronizationSettings":"false","ExportRelationshipRoles":"false","ExportSales":"false"}},{"environment":{},"enabled":true,"continueOnError":false,"alwaysRun":false,"displayName":"Publish Pipeline Artifact","timeoutInMinutes":0,"condition":"succeeded()","task":{"id":"ecdc45f6-832d-4ad9-b52b-ee49e94659be","versionSpec":"1.*","definitionType":"task"},"inputs":{"path":"$(Pipeline.Workspace)","artifactName":"drop","artifactType":"pipeline","fileSharePath":"","parallel":"false","parallelCount":"8"}}],"name":"Agent job 1","refName":"Job_1","condition":"succeeded()","target":{"executionOptions":{"type":0},"allowScriptsAuthAccessOption":false,"type":1},"jobAuthorizationScope":1}],"target":{"agentSpecification":{"identifier":"vs2017-win2016"}},"type":1},"repository":{"properties":{"cleanOptions":"0","labelSources":"0","labelSourcesFormat":"$(build.buildNumber)","reportBuildStatus":"true","gitLfsSupport":"false","skipSyncSource":"false","checkoutNestedSubmodules":"false","fetchDepth":"0"},"id":"c45bae99-de15-4ff8-8716-792433bcc295","type":"TfsGit","name":"Assets-Demo","url":"https://dev.azure.com/shandemo/Assets-Demo/_git/Assets-Demo","defaultBranch":"refs/heads/master","clean":"false","checkoutSubmodules":false},"processParameters":{},"quality":1,"authoredBy":{"displayName":"Shan McArthur","url":"https://spsprodcus1.vssps.visualstudio.com/A28f9aaa1-72fe-494d-8879-af0ab6f31dd1/_apis/Identities/ebef9cf4-497d-6997-9524-f7e2ac32df22","_links":{"avatar":{"href":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"}},"id":"ebef9cf4-497d-6997-9524-f7e2ac32df22","uniqueName":"admin@shandemo.onmicrosoft.com","imageUrl":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy","descriptor":"aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"},"drafts":[],"queue":{"_links":{"self":{"href":"https://dev.azure.com/shandemo/_apis/build/Queues/24"}},"id":24,"name":"Azure Pipelines","url":"https://dev.azure.com/shandemo/_apis/build/Queues/24","pool":{"id":9,"name":"Azure Pipelines","isHosted":true}},"id":7,"name":"Build Managed Solution","url":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_apis/build/Definitions/7?revision=3","uri":"vstfs:///Build/Definition/7","path":"\\","type":2,"queueStatus":0,"revision":3,"createdDate":"2019-10-23T17:26:54.683Z","project":{"id":"005fdef2-7157-447c-a363-f9f4148741eb","name":"Assets-Demo","description":"Azure DevOps demo for Dynamics 365 CDS","url":"https://dev.azure.com/shandemo/_apis/projects/005fdef2-7157-447c-a363-f9f4148741eb","state":1,"revision":20,"visibility":0,"lastUpdateTime":"2019-02-07T19:32:01.537Z"}}
--------------------------------------------------------------------------------
/Lab Resources/Deploy to Production.json:
--------------------------------------------------------------------------------
1 | {"source":2,"revision":5,"description":null,"createdBy":{"displayName":"Shan McArthur","url":"https://spsprodcus1.vssps.visualstudio.com/A28f9aaa1-72fe-494d-8879-af0ab6f31dd1/_apis/Identities/ebef9cf4-497d-6997-9524-f7e2ac32df22","_links":{"avatar":{"href":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"}},"id":"ebef9cf4-497d-6997-9524-f7e2ac32df22","uniqueName":"admin@shandemo.onmicrosoft.com","imageUrl":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy","descriptor":"aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"},"createdOn":"2019-10-14T19:48:53.227Z","modifiedBy":{"displayName":"Shan McArthur","url":"https://spsprodcus1.vssps.visualstudio.com/A28f9aaa1-72fe-494d-8879-af0ab6f31dd1/_apis/Identities/ebef9cf4-497d-6997-9524-f7e2ac32df22","_links":{"avatar":{"href":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"}},"id":"ebef9cf4-497d-6997-9524-f7e2ac32df22","uniqueName":"admin@shandemo.onmicrosoft.com","imageUrl":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy","descriptor":"aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"},"modifiedOn":"2019-10-14T19:58:12.250Z","isDeleted":false,"lastRelease":{"id":23,"name":"Release-3","artifacts":[],"_links":{},"description":"","releaseDefinition":{"id":4,"projectReference":null,"_links":{}},"createdOn":"2019-10-14T19:58:15.680Z","createdBy":{"displayName":"Shan McArthur","url":"https://spsprodcus1.vssps.visualstudio.com/A28f9aaa1-72fe-494d-8879-af0ab6f31dd1/_apis/Identities/ebef9cf4-497d-6997-9524-f7e2ac32df22","_links":{"avatar":{"href":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"}},"id":"ebef9cf4-497d-6997-9524-f7e2ac32df22","uniqueName":"admin@shandemo.onmicrosoft.com","imageUrl":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy","descriptor":"aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"}},"variables":{"SolutionName":{"value":"AssetManagement"}},"variableGroups":[],"environments":[{"id":5,"name":"Stage 1","rank":1,"owner":{"displayName":"Shan McArthur","url":"https://spsprodcus1.vssps.visualstudio.com/A28f9aaa1-72fe-494d-8879-af0ab6f31dd1/_apis/Identities/ebef9cf4-497d-6997-9524-f7e2ac32df22","_links":{"avatar":{"href":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"}},"id":"ebef9cf4-497d-6997-9524-f7e2ac32df22","uniqueName":"admin@shandemo.onmicrosoft.com","imageUrl":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy","descriptor":"aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"},"variables":{},"variableGroups":[],"preDeployApprovals":{"approvals":[{"rank":1,"isAutomated":true,"isNotificationOn":false,"id":13}],"approvalOptions":{"requiredApproverCount":null,"releaseCreatorCanBeApprover":false,"autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped":false,"enforceIdentityRevalidation":false,"timeoutInMinutes":0,"executionOrder":1}},"deployStep":{"id":14},"postDeployApprovals":{"approvals":[{"rank":1,"isAutomated":true,"isNotificationOn":false,"id":15}],"approvalOptions":{"requiredApproverCount":null,"releaseCreatorCanBeApprover":false,"autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped":false,"enforceIdentityRevalidation":false,"timeoutInMinutes":0,"executionOrder":2}},"deployPhases":[{"deploymentInput":{"parallelExecution":{"parallelExecutionType":0},"agentSpecification":{"identifier":"vs2017-win2016"},"skipArtifactsDownload":false,"artifactsDownloadInput":{"downloadInputs":[]},"queueId":24,"demands":[],"enableAccessToken":false,"timeoutInMinutes":0,"jobCancelTimeoutInMinutes":1,"condition":"succeeded()","overrideInputs":{}},"rank":1,"phaseType":1,"name":"Agent job","refName":null,"workflowTasks":[{"environment":{},"taskId":"20f1587d-7424-466b-9208-baa837bb020f","version":"0.*","name":"PowerApps Tool Installer ","refName":"","enabled":true,"alwaysRun":false,"continueOnError":false,"timeoutInMinutes":0,"definitionType":"task","overrideInputs":{},"condition":"succeeded()","inputs":{"XrmOnlineManagementApiVersion":"1.1.0.9053","XrmToolingCrmConnectorVersion":"3.3.0.834","XrmToolingPackageDeploymentVersion":"3.3.0.833","MicrosoftPowerAppsCheckerVersion":"1.0.2","CrmSdkCoreToolsVersion":"9.0.3.1"}},{"environment":{},"taskId":"d9bafed4-0b18-4f58-968d-86655b4d2ce9","version":"2.*","name":"Command Line Script","refName":"","enabled":false,"alwaysRun":false,"continueOnError":false,"timeoutInMinutes":0,"definitionType":"task","overrideInputs":{},"condition":"succeeded()","inputs":{"script":"echo Write your commands here\n\ndir /s\n","workingDirectory":"","failOnStderr":"false"}},{"environment":{},"taskId":"89fa86fd-4b50-4d77-8c5f-a876e7a3e2dd","version":"0.*","name":"PowerApps Import Solution ","refName":"","enabled":true,"alwaysRun":false,"continueOnError":false,"timeoutInMinutes":0,"definitionType":"task","overrideInputs":{},"condition":"succeeded()","inputs":{"PowerAppsEnvironment":"9432d45d-1f69-42d2-abc9-beee4d378a7d","SolutionInputFile":"$(System.DefaultWorkingDirectory)/drop/drop/a/$(SolutionName)_managed.zip","ConvertToManaged":"false","HoldingSolution":"false","OverwriteUnmanagedCustomizations":"false","PublishWorkflows":"false","SkipProductUpdateDependencies":"false"}}]}],"environmentOptions":{"emailNotificationType":"OnlyOnFailure","emailRecipients":"release.environment.owner;release.creator","skipArtifactsDownload":false,"timeoutInMinutes":0,"enableAccessToken":false,"publishDeploymentStatus":true,"badgeEnabled":false,"autoLinkWorkItems":false,"pullRequestDeploymentEnabled":false},"demands":[],"conditions":[{"name":"ReleaseStarted","conditionType":1,"value":""}],"executionPolicy":{"concurrencyCount":1,"queueDepthCount":0},"schedules":[],"currentRelease":{"id":23,"url":"https://vsrm.dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_apis/Release/releases/23","_links":{}},"retentionPolicy":{"daysToKeep":30,"releasesToKeep":3,"retainBuild":true},"processParameters":{},"properties":{"BoardsEnvironmentType":{"$type":"System.String","$value":"unmapped"},"LinkBoardsWorkItems":{"$type":"System.String","$value":"False"}},"preDeploymentGates":{"id":0,"gatesOptions":null,"gates":[]},"postDeploymentGates":{"id":0,"gatesOptions":null,"gates":[]},"environmentTriggers":[],"badgeUrl":"https://vsrm.dev.azure.com/shandemo/_apis/public/Release/badge/005fdef2-7157-447c-a363-f9f4148741eb/4/5"}],"artifacts":[{"sourceId":"005fdef2-7157-447c-a363-f9f4148741eb:7","type":"Build","alias":"drop","definitionReference":{"artifactSourceDefinitionUrl":{"id":"https://dev.azure.com/shandemo/_permalink/_build/index?collectionId=a882f0f1-f3fb-4129-ac9a-d4b7956ca289&projectId=005fdef2-7157-447c-a363-f9f4148741eb&definitionId=7","name":""},"defaultVersionBranch":{"id":"","name":""},"defaultVersionSpecific":{"id":"","name":""},"defaultVersionTags":{"id":"","name":""},"defaultVersionType":{"id":"latestType","name":"Latest"},"definition":{"id":"7","name":"Build Managed Solution"},"definitions":{"id":"","name":""},"IsMultiDefinitionType":{"id":"False","name":"False"},"project":{"id":"005fdef2-7157-447c-a363-f9f4148741eb","name":"Assets-Demo"},"repository":{"id":"","name":""}},"isPrimary":true,"isRetained":false}],"triggers":[],"releaseNameFormat":"Release-$(rev:r)","tags":[],"properties":{"DefinitionCreationSource":{"$type":"System.String","$value":"ReleaseNew"},"IntegrateBoardsWorkItems":{"$type":"System.String","$value":"False"},"IntegrateJiraWorkItems":{"$type":"System.String","$value":"false"}},"id":4,"name":"Deploy to Production","path":"\\","projectReference":null,"url":"https://vsrm.dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_apis/Release/definitions/4","_links":{"self":{"href":"https://vsrm.dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_apis/Release/definitions/4"},"web":{"href":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_release?definitionId=4"}}}
--------------------------------------------------------------------------------
/Lab Resources/Export From Dev.json:
--------------------------------------------------------------------------------
1 | {"options":[{"enabled":false,"definition":{"id":"5d58cc01-7c75-450c-be18-a388ddb129ec"},"inputs":{"branchFilters":"[\"+refs/heads/*\"]","additionalFields":"{}"}},{"enabled":false,"definition":{"id":"a9db38f9-9fdc-478c-b0f9-464221e58316"},"inputs":{"workItemType":"Bug","assignToRequestor":"true","additionalFields":"{}"}}],"variables":{"SolutionName":{"value":"AssetManagement"},"system.debug":{"value":"false","allowOverride":true}},"properties":{},"tags":[],"_links":{"self":{"href":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_apis/build/Definitions/9?revision=2"},"web":{"href":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_build/definition?definitionId=9"},"editor":{"href":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_build/designer?id=9&_a=edit-build-definition"},"badge":{"href":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_apis/build/status/9"}},"jobAuthorizationScope":1,"jobTimeoutInMinutes":60,"jobCancelTimeoutInMinutes":5,"process":{"phases":[{"steps":[{"environment":{},"enabled":true,"continueOnError":false,"alwaysRun":false,"displayName":"PowerApps Tool Installer ","timeoutInMinutes":0,"condition":"succeeded()","task":{"id":"20f1587d-7424-466b-9208-baa837bb020f","versionSpec":"0.*","definitionType":"task"},"inputs":{"XrmOnlineManagementApiVersion":"1.1.0.9053","XrmToolingCrmConnectorVersion":"3.3.0.834","XrmToolingPackageDeploymentVersion":"3.3.0.833","MicrosoftPowerAppsCheckerVersion":"1.0.2","CrmSdkCoreToolsVersion":"9.0.3.1"}},{"environment":{},"enabled":true,"continueOnError":false,"alwaysRun":false,"displayName":"PowerApps Export Solution ","timeoutInMinutes":0,"condition":"succeeded()","task":{"id":"c8b391bf-3134-4c03-9965-3af46ce54a4d","versionSpec":"0.*","definitionType":"task"},"inputs":{"PowerAppsEnvironment":"86248b74-fa5d-4574-a3ad-08a3e3f53a1c","SolutionName":"$(SolutionName)","SolutionOutputFile":"$(Build.ArtifactStagingDirectory)\\$(SolutionName).zip","Managed":"false","ExportAutoNumberingSettings":"false","ExportCalendarSettings":"false","ExportCustomizationSettings":"false","ExportEmailTrackingSettings":"false","ExportGeneralSettings":"false","ExportIsvConfig":"false","ExportMarketingSettings":"false","ExportOutlookSynchronizationSettings":"false","ExportRelationshipRoles":"false","ExportSales":"false"}},{"environment":{},"enabled":true,"continueOnError":false,"alwaysRun":false,"displayName":"PowerApps Unpack Solution ","timeoutInMinutes":0,"condition":"succeeded()","task":{"id":"9d571c2a-157d-4987-8e52-842e741a9256","versionSpec":"0.*","definitionType":"task"},"inputs":{"SolutionInputFile":"$(Build.ArtifactStagingDirectory)\\$(SolutionName).zip","SolutionTargetFolder":"CdsConfig","SolutionType":"Unmanaged","OverwriteFiles":"true"}},{"environment":{},"enabled":true,"continueOnError":false,"alwaysRun":false,"displayName":"Command Line Script","timeoutInMinutes":0,"condition":"succeeded()","task":{"id":"d9bafed4-0b18-4f58-968d-86655b4d2ce9","versionSpec":"2.*","definitionType":"task"},"inputs":{"script":"echo commit all changes\ngit config user.email \"admin@shandemo.onmicrosoft.com\"\ngit config user.name \"Automated Build\"\ngit checkout master\ngit add --all\ngit commit -m \"solution init\"\necho push code to new repo\ngit -c http.extraheader=\"AUTHORIZATION: bearer $(System.AccessToken)\" push origin master","workingDirectory":"","failOnStderr":"false"}}],"name":"Agent job 1","refName":"Job_1","condition":"succeeded()","target":{"executionOptions":{"type":0},"allowScriptsAuthAccessOption":true,"type":1},"jobAuthorizationScope":1}],"target":{"agentSpecification":{"identifier":"vs2017-win2016"}},"type":1},"repository":{"properties":{"cleanOptions":"0","labelSources":"0","labelSourcesFormat":"$(build.buildNumber)","reportBuildStatus":"true","gitLfsSupport":"false","skipSyncSource":"false","checkoutNestedSubmodules":"false","fetchDepth":"0"},"id":"c45bae99-de15-4ff8-8716-792433bcc295","type":"TfsGit","name":"Assets-Demo","url":"https://dev.azure.com/shandemo/Assets-Demo/_git/Assets-Demo","defaultBranch":"refs/heads/master","clean":"false","checkoutSubmodules":false},"processParameters":{},"quality":1,"authoredBy":{"displayName":"Shan McArthur","url":"https://spsprodcus1.vssps.visualstudio.com/A28f9aaa1-72fe-494d-8879-af0ab6f31dd1/_apis/Identities/ebef9cf4-497d-6997-9524-f7e2ac32df22","_links":{"avatar":{"href":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"}},"id":"ebef9cf4-497d-6997-9524-f7e2ac32df22","uniqueName":"admin@shandemo.onmicrosoft.com","imageUrl":"https://dev.azure.com/shandemo/_apis/GraphProfile/MemberAvatars/aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy","descriptor":"aad.ZWJlZjljZjQtNDk3ZC03OTk3LTk1MjQtZjdlMmFjMzJkZjIy"},"drafts":[],"queue":{"_links":{"self":{"href":"https://dev.azure.com/shandemo/_apis/build/Queues/24"}},"id":24,"name":"Azure Pipelines","url":"https://dev.azure.com/shandemo/_apis/build/Queues/24","pool":{"id":9,"name":"Azure Pipelines","isHosted":true}},"id":9,"name":"Export From Dev","url":"https://dev.azure.com/shandemo/005fdef2-7157-447c-a363-f9f4148741eb/_apis/build/Definitions/9?revision=2","uri":"vstfs:///Build/Definition/9","path":"\\","type":2,"queueStatus":0,"revision":2,"createdDate":"2019-10-14T20:29:47.753Z","project":{"id":"005fdef2-7157-447c-a363-f9f4148741eb","name":"Assets-Demo","description":"Azure DevOps demo for Dynamics 365 CDS","url":"https://dev.azure.com/shandemo/_apis/projects/005fdef2-7157-447c-a363-f9f4148741eb","state":1,"revision":20,"visibility":0,"lastUpdateTime":"2019-02-07T19:32:01.537Z"}}
--------------------------------------------------------------------------------
/Lab Resources/Hands-on with Power Apps and Azure.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerApps-Azure-Lab/2af6a6bbaa235f1e3aec38743703a6eae9dda665/Lab Resources/Hands-on with Power Apps and Azure.pptx
--------------------------------------------------------------------------------
/Lab Resources/Hands-on with PowerApps and Azure-Lab Document.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerApps-Azure-Lab/2af6a6bbaa235f1e3aec38743703a6eae9dda665/Lab Resources/Hands-on with PowerApps and Azure-Lab Document.docx
--------------------------------------------------------------------------------
/Lab Resources/Hands-on with PowerApps and Azure-Lab Document.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerApps-Azure-Lab/2af6a6bbaa235f1e3aec38743703a6eae9dda665/Lab Resources/Hands-on with PowerApps and Azure-Lab Document.pdf
--------------------------------------------------------------------------------
/Lab Resources/Product.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Lab Resources/Products_list_icon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerApps-Azure-Lab/2af6a6bbaa235f1e3aec38743703a6eae9dda665/Lab Resources/Products_list_icon.jpg
--------------------------------------------------------------------------------
/Lab Resources/Swagger.json:
--------------------------------------------------------------------------------
1 | {
2 | "swagger": "2.0",
3 | "info": {
4 | "version": "v1",
5 | "title": "ProductListAPI"
6 | },
7 | "host": "UseYourWebAppName.azurewebsites.net",
8 | "schemes": [ "http" ],
9 | "paths": {
10 | "/products": {
11 | "get": {
12 | "tags": [ "Products" ],
13 | "summary": "Gets the list of products",
14 | "description": "This operation returns the list of products along with their current stock",
15 | "operationId": "GetAllProducts",
16 | "consumes": [],
17 | "produces": [ "application/json", "text/json", "application/xml", "text/xml" ],
18 | "responses": {
19 | "200": {
20 | "description": "OK",
21 | "schema": {
22 | "type": "array",
23 | "items": { "$ref": "#/definitions/Product" }
24 | }
25 | }
26 | }
27 | },
28 | "post": {
29 | "tags": [ "Products" ],
30 | "summary": "Creates a new product",
31 | "description": "This operation creates a new product along with it's current stock",
32 | "operationId": "CreateProduct",
33 | "consumes": [ "application/json", "text/json", "application/xml", "text/xml", "application/x-www-form-urlencoded" ],
34 | "produces": [ "application/json", "text/json", "application/xml", "text/xml" ],
35 | "parameters": [
36 | {
37 | "name": "product",
38 | "in": "body",
39 | "description": "The new product",
40 | "required": true,
41 | "schema": { "$ref": "#/definitions/Product" }
42 | }
43 | ],
44 | "responses": {
45 | "200": {
46 | "description": "OK",
47 | "schema": { "$ref": "#/definitions/Product" }
48 | },
49 | "201": {
50 | "description": "Created",
51 | "schema": { "$ref": "#/definitions/Product" }
52 | }
53 | }
54 | },
55 | "delete": {
56 | "tags": [ "Products" ],
57 | "summary": "Deletes all products",
58 | "description": "This operation deletes all the products from the inventory",
59 | "operationId": "DeleteAllProducts",
60 | "consumes": [],
61 | "produces": [ "application/json", "text/json", "application/xml", "text/xml" ],
62 | "responses": {
63 | "200": {
64 | "description": "OK",
65 | "schema": { "type": "boolean" }
66 | }
67 | }
68 | }
69 | },
70 | "/products/{id}": {
71 | "get": {
72 | "tags": [ "Products" ],
73 | "summary": "Gets a specific product",
74 | "description": "This operation returns the specific product based on the ID along with it's current stock",
75 | "operationId": "GetProductById",
76 | "consumes": [],
77 | "produces": [ "application/json", "text/json", "application/xml", "text/xml" ],
78 | "parameters": [
79 | {
80 | "name": "id",
81 | "in": "path",
82 | "description": "Identifier for the product",
83 | "required": true,
84 | "type": "integer",
85 | "format": "int32"
86 | }
87 | ],
88 | "responses": {
89 | "200": {
90 | "description": "OK",
91 | "schema": { "$ref": "#/definitions/Product" }
92 | },
93 | "404": {
94 | "description": "Product not found",
95 | "schema": { "$ref": "#/definitions/Product" }
96 | }
97 | }
98 | },
99 | "delete": {
100 | "tags": [ "Products" ],
101 | "summary": "Deletes a product",
102 | "description": "This operation deletes the product from the inventory",
103 | "operationId": "DeleteProductById",
104 | "consumes": [],
105 | "produces": [ "application/json", "text/json", "application/xml", "text/xml" ],
106 | "parameters": [
107 | {
108 | "name": "id",
109 | "in": "path",
110 | "description": "Identifier of the product to be deleted",
111 | "required": true,
112 | "type": "integer",
113 | "format": "int32"
114 | }
115 | ],
116 | "responses": {
117 | "200": {
118 | "description": "OK",
119 | "schema": { "type": "boolean" }
120 | },
121 | "404": {
122 | "description": "Product not found",
123 | "schema": { "type": "boolean" }
124 | }
125 | }
126 | }
127 | },
128 | "/products/{ProductId}": {
129 | "post": {
130 | "tags": [ "Products" ],
131 | "summary": "Update a specific product",
132 | "description": "This operation updates the specific product based on the ID along with it's current stock",
133 | "operationId": "UpdateProduct",
134 | "consumes": [ "application/json", "text/json", "application/xml", "text/xml", "application/x-www-form-urlencoded" ],
135 | "produces": [ "application/json", "text/json", "application/xml", "text/xml" ],
136 | "parameters": [
137 | {
138 | "name": "product",
139 | "in": "body",
140 | "description": "Product to update inluding ID",
141 | "required": true,
142 | "schema": { "$ref": "#/definitions/Product" }
143 | },
144 | {
145 | "name": "ProductId",
146 | "in": "path",
147 | "description": "Product Id to update",
148 | "required": true,
149 | "type": "integer",
150 | "format": "int32"
151 | }
152 | ],
153 | "responses": {
154 | "200": {
155 | "description": "OK",
156 | "schema": { "type": "boolean" }
157 | },
158 | "404": {
159 | "description": "Product not found",
160 | "schema": { "type": "boolean" }
161 | }
162 | }
163 | }
164 | }
165 | },
166 | "definitions": {
167 | "Product": {
168 | "description": "Product",
169 | "type": "object",
170 | "properties": {
171 | "Id": {
172 | "format": "int32",
173 | "description": "The ID of the product.",
174 | "type": "integer"
175 | },
176 | "Name": {
177 | "description": "Product name.",
178 | "type": "string"
179 | },
180 | "CurrentInventory": {
181 | "format": "int32",
182 | "description": "Current Inventory",
183 | "type": "integer"
184 | },
185 | "Unit": {
186 | "description": "The Product's unit.",
187 | "type": "string"
188 | }
189 | }
190 | }
191 | }
192 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Power Apps & Azure Lab
2 |
3 |
10 | This repository contains a source code for an API App and a lab manual for demonstrating a simple example for integrating Power Apps Canvas apps with an API app hosted on an Azure Web App using a custom-connector. This scenario can be used to unlock the potential of untapped assets within an enterprise (legacy APIs, data sources, processes etc..)
11 |
12 | ## Lab Overview & Objective
13 |
14 | ### Overview
15 |
16 | Most enterprises have a majority of their core business data trapped in several silos (legacy databases & apps - Systems of Records). It is essential for digital transformation to break those data silos and make the information trapped in those systems available to employees and business teams as needed.
17 |
18 | It is also important to modernize the user experience of the enterprise apps in order to drive productivity.
19 |
20 | [Microsoft Power Apps](https://docs.microsoft.com/en-us/powerapps/powerapps-overview) along with [Azure](https://docs.microsoft.com/en-us/azure/guides/developer/azure-developer-guide) could be an effective way to bridge this gap, by enabling an RESTful API layer powered by Azure which could encapsulate and standardize the enterprise data for use with apps + Power Apps as the rapid application development User interface where business apps can be built with agility and in collaboration with the business.
21 |
22 | ### Objectives
23 |
24 | This lab has two key objectives:
25 | - To demonstrate how Power Apps platform can help unlock the potential of untapped assets within an Enterprise ( legacy APIs, data sources, processes) with a low-code / no code approach.
26 | - Learn to create a cross-platform application user experience using Microsoft Power Apps to consume these RESTful APIs through custom connectors
27 | - `[Optional/Bonus Lab]` Learn how to enable Application Lifecycle Management (ALM) and setup Azure DevOps for the application
28 |
29 | ## Prerequisites
30 |
31 | The lab requires:
32 | - Visual Studio 2017 or 2019 to compile the code and publish to Azure
33 | - Access to an Azure Subscription to create an API app to serve as the RESTful API
34 | - Access to a Power Apps environment with Maker permission to create apps and custom connectors
35 |
36 | ## Lab Manual
37 |
38 | Refer to the [Lab Document](https://github.com/microsoft/PowerApps-Azure-Lab/blob/master/Lab%20Resources/Hands-on%20with%20PowerApps%20and%20Azure-Lab%20Document.pdf) for the step-by-step guidance for this lab.
39 |
40 | ## Key concepts
41 |
42 | - [Microsoft Power Apps](https://docs.microsoft.com/en-us/powerapps/powerapps-overview)
43 | - [Custom Connectors](https://docs.microsoft.com/en-us/connectors/custom-connectors/)
44 | - [ALM for Power Apps](https://docs.microsoft.com/en-us/power-platform/admin/automate-alm)
45 |
46 | ## Contents
47 |
48 | | File/folder | Description |
49 | |-------------------|--------------------------------------------|
50 | | `Lab Resources` | Lab Resources including Lab Manual. |
51 | | `src` | Source code for the API App. |
52 | | `README.md` | This README file. |
53 | | `LICENSE` | The license for the lab. |
54 |
55 |
56 | ## Contributing
57 |
58 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
59 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
60 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
61 |
62 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide
63 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
64 | provided by the bot. You will only need to do this once across all repos using our CLA.
65 |
66 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
67 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
68 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
69 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/ProductListAPI.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29424.173
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductListAPI", "ProductListAPI\ProductListAPI.csproj", "{12B6DD58-3A99-4DDE-9013-3720DEC683F4}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {12B6DD58-3A99-4DDE-9013-3720DEC683F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {12B6DD58-3A99-4DDE-9013-3720DEC683F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {12B6DD58-3A99-4DDE-9013-3720DEC683F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {12B6DD58-3A99-4DDE-9013-3720DEC683F4}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {C1F00C5E-7405-4B1B-9034-14A365D850BB}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/src/ProductListAPI/App_Start/GenericStorage.cs:
--------------------------------------------------------------------------------
1 | using ProductListAPI.Models;
2 | using Newtonsoft.Json;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Reflection;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace ProductListAPI
12 | {
13 | internal class GenericStorage
14 | {
15 | private string _filePath;
16 |
17 | public GenericStorage()
18 | {
19 | var webAppsHome = Environment.GetEnvironmentVariable("HOME")?.ToString();
20 | if (String.IsNullOrEmpty(webAppsHome))
21 | {
22 | _filePath = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath) + "\\";
23 | }
24 | else
25 | {
26 | _filePath = webAppsHome + "\\site\\wwwroot\\";
27 | }
28 | }
29 |
30 | public void Save(IEnumerable target, string filename)
31 | {
32 | var json = JsonConvert.SerializeObject(target);
33 | File.WriteAllText(_filePath + filename, json);
34 | }
35 |
36 | public IEnumerable Get(string filename)
37 | {
38 | var records = String.Empty;
39 | if (File.Exists(_filePath + filename))
40 | {
41 | records = File.ReadAllText(_filePath + filename);
42 | }
43 |
44 | var Products = JsonConvert.DeserializeObject(records);
45 | return Products;
46 | }
47 |
48 | public void Delete(string filename)
49 | {
50 | File.Delete(filename);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/ProductListAPI/App_Start/SwaggerConfig.cs:
--------------------------------------------------------------------------------
1 | using System.Web.Http;
2 | using System.Web.Http.Description;
3 | using Swashbuckle.Application;
4 | using Swashbuckle.Swagger;
5 | using WebActivatorEx;
6 | using ProductListAPI;
7 | using System;
8 | using System.Reflection;
9 | using System.IO;
10 | using System.Linq;
11 | using System.Globalization;
12 |
13 | [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
14 |
15 | namespace ProductListAPI
16 | {
17 | ///
18 | /// Swagger Config file
19 | ///
20 | internal class SwaggerConfig
21 | {
22 | internal static void Register()
23 | {
24 | var thisAssembly = typeof(SwaggerConfig).Assembly;
25 |
26 | GlobalConfiguration.Configuration
27 | .EnableSwagger(c =>
28 | {
29 | // By default, the service root url is inferred from the request used to access the docs.
30 | // However, there may be situations (e.g. proxy and load-balanced environments) where this does not
31 | // resolve correctly. You can workaround this by providing your own code to determine the root URL.
32 | //
33 | //c.RootUrl(req => GetRootUrlFromAppConfig());
34 |
35 | // If schemes are not explicitly provided in a Swagger 2.0 document, then the scheme used to access
36 | // the docs is taken as the default. If your API supports multiple schemes and you want to be explicit
37 | // about them, you can use the "Schemes" option as shown below.
38 | //
39 | //c.Schemes(new[] { "http", "https" });
40 |
41 | // Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to
42 | // hold additional metadata for an API. Version and title are required but you can also provide
43 | // additional fields by chaining methods off SingleApiVersion.
44 | //
45 | c.SingleApiVersion("v1", "ProductListAPI");
46 |
47 | // If you want the output Swagger docs to be indented properly, enable the "PrettyPrint" option.
48 | //
49 | //c.PrettyPrint();
50 |
51 | // If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
52 | // In this case, you must provide a lambda that tells Swashbuckle which actions should be
53 | // included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
54 | // returns an "Info" builder so you can provide additional metadata per API version.
55 | //
56 | //c.MultipleApiVersions(
57 | // (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
58 | // (vc) =>
59 | // {
60 | // vc.Version("v2", "Swashbuckle Dummy API V2");
61 | // vc.Version("v1", "Swashbuckle Dummy API V1");
62 | // });
63 |
64 | // You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
65 | // See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
66 | // NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
67 | // at the document or operation level to indicate which schemes are required for an operation. To do this,
68 | // you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
69 | // according to your specific authorization implementation
70 | //
71 | //c.BasicAuth("basic")
72 | // .Description("Basic HTTP Authentication");
73 | //
74 | // NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
75 | //c.ApiKey("apiKey")
76 | // .Description("API Key Authentication")
77 | // .Name("apiKey")
78 | // .In("header");
79 | //
80 | //c.OAuth2("oauth2")
81 | // .Description("OAuth2 Implicit Grant")
82 | // .Flow("implicit")
83 | // .AuthorizationUrl("http://petstore.swagger.wordnik.com/api/oauth/dialog")
84 | // //.TokenUrl("https://tempuri.org/token")
85 | // .Scopes(scopes =>
86 | // {
87 | // scopes.Add("read", "Read access to protected resources");
88 | // scopes.Add("write", "Write access to protected resources");
89 | // });
90 |
91 | // Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
92 | //c.IgnoreObsoleteActions();
93 |
94 | // Each operation be assigned one or more tags which are then used by consumers for various reasons.
95 | // For example, the swagger-ui groups operations according to the first tag of each operation.
96 | // By default, this will be controller name but you can use the "GroupActionsBy" option to
97 | // override with any value.
98 | //
99 | //c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
100 |
101 | // You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
102 | // the order in which operations are listed. For example, if the default grouping is in place
103 | // (controller name) and you specify a descending alphabetic sort order, then actions from a
104 | // ProductsController will be listed before those from a CustomersController. This is typically
105 | // used to customize the order of groupings in the swagger-ui.
106 | //
107 | //c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
108 |
109 | // If you annotate Controllers and API Types with
110 | // Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
111 | // those comments into the generated docs and UI. You can enable this by providing the path to one or
112 | // more Xml comment files.
113 | //
114 | c.IncludeXmlComments(GetXmlCommentsPath());
115 |
116 | // Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
117 | // exposed in your API. However, there may be occasions when more control of the output is needed.
118 | // This is supported through the "MapType" and "SchemaFilter" options:
119 | //
120 | // Use the "MapType" option to override the Schema generation for a specific type.
121 | // It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
122 | // While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
123 | // It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
124 | // use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
125 | // complex Schema, use a Schema filter.
126 | //
127 | //c.MapType(() => new Schema { type = "integer", format = "int32" });
128 |
129 | // If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
130 | // specific type, you can wire up one or more Schema filters.
131 | //
132 | //c.SchemaFilter();
133 |
134 | // In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
135 | // Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
136 | // works well because it prevents the "implementation detail" of type namespaces from leaking into your
137 | // Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
138 | // need to opt out of this behavior to avoid Schema Id conflicts.
139 | //
140 | //c.UseFullTypeNameInSchemaIds();
141 |
142 | // Alternatively, you can provide your own custom strategy for inferring SchemaId's for
143 | // describing "complex" types in your API.
144 | //
145 | //c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName);
146 |
147 | // Set this flag to omit schema property descriptions for any type properties decorated with the
148 | // Obsolete attribute
149 | //c.IgnoreObsoleteProperties();
150 |
151 | // In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
152 | // You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
153 | // enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
154 | // approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
155 | //
156 | //c.DescribeAllEnumsAsStrings();
157 |
158 | // Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
159 | //
160 | // Post-modify Operation descriptions once they've been generated by wiring up one or more
161 | // Operation filters.
162 | //
163 | //c.OperationFilter();
164 | //
165 | // If you've defined an OAuth2 flow as described above, you could use a custom filter
166 | // to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
167 | // to execute the operation
168 | //
169 | //c.OperationFilter();
170 | //
171 | // Set filter to eliminate duplicate operation ids from being generated
172 | // when there are multiple operations with the same verb in the API.
173 | //
174 | //c.OperationFilter();
175 |
176 | // Post-modify the entire Swagger document by wiring up one or more Document filters.
177 | // This gives full control to modify the final SwaggerDocument. You should have a good understanding of
178 | // the Swagger 2.0 spec. - https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md
179 | // before using this option.
180 | //
181 | //c.DocumentFilter();
182 |
183 | // In contrast to WebApi, Swagger 2.0 does not include the query string component when mapping a URL
184 | // to an action. As a result, Swashbuckle will raise an exception if it encounters multiple actions
185 | // with the same path (sans query string) and HTTP method. You can workaround this by providing a
186 | // custom strategy to pick a winner or merge the descriptions for the purposes of the Swagger docs
187 | //
188 | //c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
189 |
190 | // Wrap the default SwaggerGenerator with additional behavior (e.g. caching) or provide an
191 | // alternative implementation for ISwaggerProvider with the CustomProvider option.
192 | //
193 | //c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
194 | })
195 | .EnableSwaggerUi(c =>
196 | {
197 | // Use the "DocumentTitle" option to change the Document title.
198 | // Very helpful when you have multiple Swagger pages open, to tell them apart.
199 | //
200 | //c.DocumentTitle("My Swagger UI");
201 |
202 | // Use the "InjectStylesheet" option to enrich the UI with one or more additional CSS stylesheets.
203 | // The file must be included in your project as an "Embedded Resource", and then the resource's
204 | // "Logical Name" is passed to the method as shown below.
205 | //
206 | //c.InjectStylesheet(containingAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");
207 |
208 | // Use the "InjectJavaScript" option to invoke one or more custom JavaScripts after the swagger-ui
209 | // has loaded. The file must be included in your project as an "Embedded Resource", and then the resource's
210 | // "Logical Name" is passed to the method as shown above.
211 | //
212 | //c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");
213 |
214 | // The swagger-ui renders boolean data types as a dropdown. By default, it provides "true" and "false"
215 | // strings as the possible choices. You can use this option to change these to something else,
216 | // for example 0 and 1.
217 | //
218 | //c.BooleanValues(new[] { "0", "1" });
219 |
220 | // By default, swagger-ui will validate specs against swagger.io's online validator and display the result
221 | // in a badge at the bottom of the page. Use these options to set a different validator URL or to disable the
222 | // feature entirely.
223 | //c.SetValidatorUrl("http://localhost/validator");
224 | //c.DisableValidator();
225 |
226 | // Use this option to control how the Operation listing is displayed.
227 | // It can be set to "None" (default), "List" (shows operations for each resource),
228 | // or "Full" (fully expanded: shows operations and their details).
229 | //
230 | //c.DocExpansion(DocExpansion.List);
231 |
232 | // Specify which HTTP operations will have the 'Try it out!' option. An empty paramter list disables
233 | // it for all operations.
234 | //
235 | //c.SupportedSubmitMethods("GET", "HEAD");
236 |
237 | // Use the CustomAsset option to provide your own version of assets used in the swagger-ui.
238 | // It's typically used to instruct Swashbuckle to return your version instead of the default
239 | // when a request is made for "index.html". As with all custom content, the file must be included
240 | // in your project as an "Embedded Resource", and then the resource's "Logical Name" is passed to
241 | // the method as shown below.
242 | //
243 | //c.CustomAsset("index", containingAssembly, "YourWebApiProject.SwaggerExtensions.index.html");
244 |
245 | // If your API has multiple versions and you've applied the MultipleApiVersions setting
246 | // as described above, you can also enable a select box in the swagger-ui, that displays
247 | // a discovery URL for each version. This provides a convenient way for users to browse documentation
248 | // for different API versions.
249 | //
250 | //c.EnableDiscoveryUrlSelector();
251 |
252 | // If your API supports the OAuth2 Implicit flow, and you've described it correctly, according to
253 | // the Swagger 2.0 specification, you can enable UI support as shown below.
254 | //
255 | //c.EnableOAuth2Support(
256 | // clientId: "test-client-id",
257 | // clientSecret: null,
258 | // realm: "test-realm",
259 | // appName: "Swagger UI"
260 | // //additionalQueryStringParams: new Dictionary() { { "foo", "bar" } }
261 | //);
262 |
263 | // If your API supports ApiKey, you can override the default values.
264 | // "apiKeyIn" can either be "query" or "header"
265 | //
266 | //c.EnableApiKeySupport("apiKey", "header");
267 | });
268 | }
269 |
270 | ///
271 | /// Returns the path to the XMLcomments
272 | ///
273 | ///
274 | private static string GetXmlCommentsPath()
275 | {
276 | var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
277 | var commentsFileName = Assembly.GetExecutingAssembly().GetName().Name + ".xml";
278 | var commentsFile = Path.Combine(baseDirectory, "bin/", commentsFileName);
279 | return commentsFile;
280 |
281 | }
282 | }
283 |
284 | internal class IncludeParameterNamesInOperationIdFilter : IOperationFilter
285 | {
286 | public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
287 | {
288 | if (operation.parameters != null)
289 | {
290 | // Select the capitalized parameter names
291 | var parameters = operation.parameters.Select(
292 | p => CultureInfo.InvariantCulture.TextInfo.ToTitleCase(p.name));
293 |
294 | // Set the operation id to match the format "OperationByParam1AndParam2"
295 | operation.operationId = string.Format(
296 | "{0}By{1}",
297 | operation.operationId,
298 | string.Join("And", parameters));
299 | }
300 | }
301 | }
302 |
303 |
304 | }
--------------------------------------------------------------------------------
/src/ProductListAPI/App_Start/WebApiConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web.Http;
5 |
6 | namespace ProductListAPI
7 | {
8 | ///
9 | /// WebApiConfig
10 | ///
11 | public static class WebApiConfig
12 | {
13 | ///
14 | /// Register
15 | ///
16 | ///
17 | public static void Register(HttpConfiguration config)
18 | {
19 | // Web API configuration and services
20 |
21 | // Web API routes
22 | config.MapHttpAttributeRoutes();
23 |
24 | config.Routes.MapHttpRoute(
25 | name: "DefaultApi",
26 | routeTemplate: "api/{controller}/{id}",
27 | defaults: new { id = RouteParameter.Optional }
28 | );
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/ProductListAPI/Controllers/ProductsController.cs:
--------------------------------------------------------------------------------
1 | using ProductListAPI.Models;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using System.Web.Http;
5 | using System.Linq;
6 | using Swashbuckle.Swagger.Annotations;
7 | using System.Net;
8 | using System.Net.Http;
9 | using System;
10 | using System.Collections;
11 | using System.Diagnostics;
12 | using Microsoft.SqlServer.Server;
13 |
14 | namespace ProductListAPI.Controllers
15 | {
16 | ///
17 | /// Products Controller
18 | ///
19 | public class ProductsController : ApiController
20 | {
21 | private const string FILENAME = "products.json";
22 | private GenericStorage _storage;
23 |
24 | ///
25 | /// Constructor
26 | ///
27 | public ProductsController()
28 | {
29 | _storage = new GenericStorage();
30 | }
31 |
32 | private IEnumerable GetInventory()
33 | {
34 | var inventory = _storage.Get(FILENAME);
35 |
36 | if (inventory == null)
37 | {
38 | //Populate with some dummy data to begin with
39 | inventory = GetDefaultProducts();
40 | _storage.Save(
41 | inventory,
42 | FILENAME);
43 | }
44 |
45 | return inventory;
46 | }
47 |
48 | private IEnumerable GetDefaultProducts()
49 | {
50 | var numProductsToInitialize = 10;
51 | Random rand = new Random();
52 | Product[] products = new Product[numProductsToInitialize];
53 | for (var i = 0; i < numProductsToInitialize; i++)
54 | {
55 | products[i] = new Product
56 | {
57 | Id = i,
58 | Name = String.Format("Widget {0}", i.ToString()),
59 | CurrentInventory = rand.Next(0, 300),
60 | Unit = "Units"
61 | };
62 | }
63 |
64 | return products;
65 |
66 | }
67 | ///
68 | /// Gets the list of products
69 | ///
70 | /// The Product inventory
71 | ///
72 | /// This operation returns the list of products along with their current stock
73 | ///
74 | [HttpGet]
75 | [SwaggerResponse(HttpStatusCode.OK,
76 | Type = typeof(IEnumerable))]
77 | [Route("~/products")]
78 | [SwaggerOperation("GetAllProducts")]
79 | public IEnumerable Get()
80 | {
81 | return GetInventory();
82 | }
83 |
84 | ///
85 | /// Gets a specific product
86 | ///
87 | /// Identifier for the product
88 | /// The requested product
89 | ///
90 | /// This operation returns the specific product based on the ID along with it's current stock
91 | ///
92 | [HttpGet]
93 | [SwaggerResponse(HttpStatusCode.OK,
94 | Description = "OK",
95 | Type = typeof(Product))]
96 | [SwaggerResponse(HttpStatusCode.NotFound,
97 | Description = "Product not found",
98 | Type = typeof(Product))]
99 | [SwaggerOperation("GetProductById")]
100 | [Route("~/products/{id}")]
101 | public Product Get([FromUri] int id)
102 | {
103 | var inventory = GetInventory();
104 | return inventory.FirstOrDefault(x => x.Id == id);
105 | }
106 |
107 | ///
108 | /// Update a specific product
109 | ///
110 | /// Product to update inluding ID
111 | /// Product Id to update
112 | /// True if update successful
113 | ///
114 | /// This operation updates the specific product based on the ID along with it's current stock
115 | ///
116 | [HttpPost]
117 | [SwaggerResponse(HttpStatusCode.OK,
118 | Description = "OK",
119 | Type = typeof(bool))]
120 | [SwaggerResponse(HttpStatusCode.NotFound,
121 | Description = "Product not found",
122 | Type = typeof(bool))]
123 | [SwaggerOperation("UpdateProduct")]
124 | [Route("~/products/{ProductId}")]
125 | public HttpResponseMessage Update([FromBody] Product product, [FromUri] int ProductId)
126 | {
127 | var inventory = GetInventory();
128 |
129 | //var productList = inventory.ToList();
130 | var curProduct = inventory.FirstOrDefault(x => x.Id == ProductId);
131 | if (curProduct == null || curProduct.Id != ProductId)
132 | {
133 | return Request.CreateResponse(HttpStatusCode.NotFound, false);
134 | }
135 | else
136 | {
137 | Delete(ProductId);
138 | Post(product);
139 | return Request.CreateResponse(HttpStatusCode.OK, true);
140 | }
141 |
142 |
143 | }
144 |
145 | ///
146 | /// Creates a new product
147 | ///
148 | /// The new product
149 | /// The saved product
150 | ///
151 | /// This operation creates a new product along with it's current stock
152 | ///
153 | [HttpPost]
154 | [SwaggerResponse(HttpStatusCode.Created,
155 | Description = "Created",
156 | Type = typeof(Product))]
157 | [Route("~/products")]
158 | [SwaggerOperation("CreateProduct")]
159 | public Product Post([FromBody] Product product)
160 | {
161 | var products = GetInventory();
162 | var productList = products.ToList();
163 | productList.Add(product);
164 | _storage.Save(productList, FILENAME);
165 | return product;
166 | }
167 |
168 | ///
169 | /// Deletes a product
170 | ///
171 | /// Identifier of the product to be deleted
172 | /// True if the product was deleted
173 | ///
174 | /// This operation deletes the product from the inventory
175 | ///
176 | [HttpDelete]
177 | [SwaggerResponse(HttpStatusCode.OK,
178 | Description = "OK",
179 | Type = typeof(bool))]
180 | [SwaggerResponse(HttpStatusCode.NotFound,
181 | Description = "Product not found",
182 | Type = typeof(bool))]
183 | [Route("~/products/{id}")]
184 | [SwaggerOperation("DeleteProductById")]
185 | public HttpResponseMessage Delete([FromUri] int id)
186 | {
187 | var products = GetInventory();
188 | var productList = products.ToList();
189 |
190 | if (!productList.Any(x => x.Id == id))
191 | {
192 | return Request.CreateResponse(HttpStatusCode.NotFound, false);
193 | }
194 | else
195 | {
196 | productList.RemoveAll(x => x.Id == id);
197 | _storage.Save(productList, FILENAME);
198 | return Request.CreateResponse(HttpStatusCode.OK, true);
199 | }
200 | }
201 |
202 | ///
203 | /// Deletes all products
204 | ///
205 | /// True if the product was deleted
206 | ///
207 | /// This operation deletes all the products from the inventory
208 | ///
209 | [HttpDelete]
210 | [SwaggerResponse(HttpStatusCode.OK,
211 | Description = "OK",
212 | Type = typeof(bool))]
213 | [Route("~/products")]
214 | [SwaggerOperation("DeleteAllProducts")]
215 | public HttpResponseMessage Delete()
216 | {
217 |
218 | _storage.Delete(FILENAME);
219 | return Request.CreateResponse(HttpStatusCode.OK, true);
220 |
221 | }
222 |
223 | }
224 | }
--------------------------------------------------------------------------------
/src/ProductListAPI/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Codebehind="Global.asax.cs" Inherits="ProductListAPI.WebApiApplication" Language="C#" %>
2 |
--------------------------------------------------------------------------------
/src/ProductListAPI/Global.asax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 | using System.Web.Http;
6 | using System.Web.Routing;
7 |
8 | namespace ProductListAPI
9 | {
10 | ///
11 | ///
12 | ///
13 | public class WebApiApplication : System.Web.HttpApplication
14 | {
15 | ///
16 | ///
17 | ///
18 | protected void Application_Start()
19 | {
20 | GlobalConfiguration.Configure(WebApiConfig.Register);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/ProductListAPI/Models/Product.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace ProductListAPI.Models
3 | {
4 | ///
5 | /// Product
6 | ///
7 | public class Product
8 | {
9 | ///
10 | /// The ID of the product.
11 | ///
12 | public int Id { get; set; }
13 |
14 | ///
15 | /// Product name.
16 | ///
17 | public string Name { get; set; }
18 |
19 |
20 | ///
21 | /// Current Inventory
22 | ///
23 | public int CurrentInventory{ get; set; }
24 |
25 | ///
26 | /// The Product's unit.
27 | ///
28 | public string Unit { get; set; }
29 |
30 | }
31 | }
--------------------------------------------------------------------------------
/src/ProductListAPI/ProductListAPI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 |
8 | 2.0
9 | {12B6DD58-3A99-4DDE-9013-3720DEC683F4}
10 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
11 | Library
12 | Properties
13 | ProductListAPI
14 | ProductListAPI
15 | v4.6.1
16 | true
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | true
27 | full
28 | false
29 | bin\
30 | DEBUG;TRACE
31 | prompt
32 | 4
33 | bin\ProductListAPI.xml
34 |
35 |
36 | pdbonly
37 | true
38 | bin\
39 | TRACE
40 | prompt
41 | 4
42 | bin\ProductListAPI.xml
43 |
44 |
45 |
46 | ..\packages\Microsoft.Azure.AppService.ApiApps.Service.0.9.64\lib\net45\Microsoft.Azure.AppService.ApiApps.Service.dll
47 |
48 |
49 |
50 | ..\packages\Microsoft.IdentityModel.JsonWebTokens.5.6.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll
51 |
52 |
53 | ..\packages\Microsoft.IdentityModel.Logging.5.6.0\lib\net461\Microsoft.IdentityModel.Logging.dll
54 |
55 |
56 | ..\packages\Microsoft.IdentityModel.Tokens.5.6.0\lib\net461\Microsoft.IdentityModel.Tokens.dll
57 |
58 |
59 | True
60 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
61 |
62 |
63 | ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
64 |
65 |
66 | ..\packages\Swashbuckle.Core.5.6.0\lib\net40\Swashbuckle.Core.dll
67 |
68 |
69 |
70 | ..\packages\System.IdentityModel.Tokens.Jwt.5.6.0\lib\net461\System.IdentityModel.Tokens.Jwt.dll
71 |
72 |
73 |
74 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.7\lib\net45\System.Web.Http.dll
87 |
88 |
89 | ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.7\lib\net45\System.Web.Http.WebHost.dll
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | ..\packages\WebActivatorEx.2.2.0\lib\net40\WebActivatorEx.dll
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | Global.asax
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | Web.config
128 |
129 |
130 | Web.config
131 |
132 |
133 |
134 |
135 | 10.0
136 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | True
146 | True
147 | 64279
148 | /
149 | http://localhost:64279/
150 | False
151 | False
152 |
153 |
154 | False
155 |
156 |
157 |
158 |
159 |
166 |
--------------------------------------------------------------------------------
/src/ProductListAPI/ProductListAPI.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug|Any CPU
5 | true
6 |
7 |
8 |
9 |
10 |
11 |
12 | plistapi - Web Deploy
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | CurrentPage
21 | True
22 | False
23 | False
24 | False
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | True
34 | False
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/ProductListAPI/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ProductListAPI")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ProductListAPI")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("889bdb3a-f9b6-428e-9ddd-96f4fcc5701f")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Revision and Build Numbers
33 | // by using the '*' as shown below:
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/src/ProductListAPI/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
--------------------------------------------------------------------------------
/src/ProductListAPI/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/src/ProductListAPI/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/ProductListAPI/apiapp.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schemas/2014-11-01/apiapp.json#",
3 | "id": "ProductListAPI",
4 | "namespace": "microsoft.com",
5 | "gateway": "2015-01-14",
6 | "version": "1.0.0",
7 | "title": "ProductListAPI",
8 | "summary": "",
9 | "author": "",
10 | "endpoints": {
11 | "apiDefinition": "/swagger/docs/v1",
12 | "status": null
13 | }
14 | }
--------------------------------------------------------------------------------
/src/ProductListAPI/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------