BeWoWebApi:
BeWoWebApi für den neuen Mobilklient BeWoPlanerMobil: .NET Version auf 4.7.2 gesetzt. GetState im Mobilklienten Abwesenheiten im Mobilklienten auskommentiert
This commit is contained in:
@@ -309,6 +309,8 @@ namespace BeWo
|
|||||||
private static String PUB_KEY = "3082010A02820101009CD30CF05AE52E47B7725D3783B3686330EAD735261925E1BDBE35F170922FB7B84B4105ABA99E350858ECB12AC468870BA3E375E4E6F3A76271BA7981601FD7919A9FF3D0786771C8690E9591CFFEE699E9603C48CC7ECA4D7712249D471B5AEBB9EC1E37001C9CAC7BA705EACE4AEBBD41E53698B9CBFD6D3C9668DF232A42900C867467C87FA59AB8526114133F65E98287CBDBFA0E56F68689F3853F9786AFB0DC1AEF6B0D95167DC42BA065B299043675806BAC4AF31B9049782FA2964F2A20252904C674C0D031CD8F31389516BAA833B843F1B11FC3307FA27931133D2D36F8E3FCF2336AB93931C5AFC48D0D1D641633AAFA8429B6D40BC0D87DC3930203010001";
|
private static String PUB_KEY = "3082010A02820101009CD30CF05AE52E47B7725D3783B3686330EAD735261925E1BDBE35F170922FB7B84B4105ABA99E350858ECB12AC468870BA3E375E4E6F3A76271BA7981601FD7919A9FF3D0786771C8690E9591CFFEE699E9603C48CC7ECA4D7712249D471B5AEBB9EC1E37001C9CAC7BA705EACE4AEBBD41E53698B9CBFD6D3C9668DF232A42900C867467C87FA59AB8526114133F65E98287CBDBFA0E56F68689F3853F9786AFB0DC1AEF6B0D95167DC42BA065B299043675806BAC4AF31B9049782FA2964F2A20252904C674C0D031CD8F31389516BAA833B843F1B11FC3307FA27931133D2D36F8E3FCF2336AB93931C5AFC48D0D1D641633AAFA8429B6D40BC0D87DC3930203010001";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private bool PinPublicKey(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
|
private bool PinPublicKey(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -336,7 +338,7 @@ namespace BeWo
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsNet45OrNewer()
|
private bool IsNet45OrNewer()
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 2012
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.29613.14
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeWoPlanerMobil", "BeWoPlanerMobil\BeWoPlanerMobil.csproj", "{284B02ED-114A-426C-9162-31BB6CF05589}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeWoPlanerMobil", "BeWoPlanerMobil\BeWoPlanerMobil.csproj", "{284B02ED-114A-426C-9162-31BB6CF05589}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Service", "Service\Service.csproj", "{094331C3-ECEE-4C89-BBFD-4C9DED89F0EF}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Service", "Service\Service.csproj", "{094331C3-ECEE-4C89-BBFD-4C9DED89F0EF}"
|
||||||
@@ -9,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Data", "Data\Data.csproj",
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Shared.csproj", "{2F50B83D-A3F0-4EC4-979A-3F9B7E3D8ED4}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Shared.csproj", "{2F50B83D-A3F0-4EC4-979A-3F9B7E3D8ED4}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeWoWebApi", "BeWoWebApi\BeWoWebApi.csproj", "{82254AC8-15C9-4BDD-B88E-04B95168CEEB}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -40,8 +44,17 @@ Global
|
|||||||
{2F50B83D-A3F0-4EC4-979A-3F9B7E3D8ED4}.DebugRemote|Any CPU.Build.0 = DebugRemote|Any CPU
|
{2F50B83D-A3F0-4EC4-979A-3F9B7E3D8ED4}.DebugRemote|Any CPU.Build.0 = DebugRemote|Any CPU
|
||||||
{2F50B83D-A3F0-4EC4-979A-3F9B7E3D8ED4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2F50B83D-A3F0-4EC4-979A-3F9B7E3D8ED4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{2F50B83D-A3F0-4EC4-979A-3F9B7E3D8ED4}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2F50B83D-A3F0-4EC4-979A-3F9B7E3D8ED4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{82254AC8-15C9-4BDD-B88E-04B95168CEEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{82254AC8-15C9-4BDD-B88E-04B95168CEEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{82254AC8-15C9-4BDD-B88E-04B95168CEEB}.DebugRemote|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{82254AC8-15C9-4BDD-B88E-04B95168CEEB}.DebugRemote|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{82254AC8-15C9-4BDD-B88E-04B95168CEEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{82254AC8-15C9-4BDD-B88E-04B95168CEEB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {75267284-7070-4045-9FC8-0FC3C56C1AD3}
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System.Web.Mvc;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Web;
|
|
||||||
using System.Web.Mvc;
|
|
||||||
using System.Web.Routing;
|
using System.Web.Routing;
|
||||||
|
|
||||||
namespace BeWoPlanerMobil
|
namespace BeWoPlanerMobil
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>BeWoPlanerMobil</RootNamespace>
|
<RootNamespace>BeWoPlanerMobil</RootNamespace>
|
||||||
<AssemblyName>BeWoPlanerMobil</AssemblyName>
|
<AssemblyName>BeWoPlanerMobil</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
<MvcBuildViews>false</MvcBuildViews>
|
<MvcBuildViews>false</MvcBuildViews>
|
||||||
<UseIISExpress>false</UseIISExpress>
|
<UseIISExpress>false</UseIISExpress>
|
||||||
<IISExpressSSLPort />
|
<IISExpressSSLPort />
|
||||||
@@ -69,6 +69,9 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\Lib\NHibernate.dll</HintPath>
|
<HintPath>..\Lib\NHibernate.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="RestSharp, Version=106.0.0.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\RestSharp.106.10.1\lib\net452\RestSharp.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
@@ -79,9 +82,9 @@
|
|||||||
<Reference Include="System.Web.Entity" />
|
<Reference Include="System.Web.Entity" />
|
||||||
<Reference Include="System.Web.ApplicationServices" />
|
<Reference Include="System.Web.ApplicationServices" />
|
||||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||||
<Reference Include="System.Web.Extensions" />
|
|
||||||
<Reference Include="System.Web" />
|
<Reference Include="System.Web" />
|
||||||
<Reference Include="System.Web.Abstractions" />
|
<Reference Include="System.Web.Abstractions" />
|
||||||
|
<Reference Include="System.Web.Extensions" />
|
||||||
<Reference Include="System.Web.Routing" />
|
<Reference Include="System.Web.Routing" />
|
||||||
<Reference Include="System.Xaml" />
|
<Reference Include="System.Xaml" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
@@ -165,6 +168,7 @@
|
|||||||
<Compile Include="Models\AbstractModel.cs" />
|
<Compile Include="Models\AbstractModel.cs" />
|
||||||
<Compile Include="Models\CustomerModel.cs" />
|
<Compile Include="Models\CustomerModel.cs" />
|
||||||
<Compile Include="Models\SchedulerModel.cs" />
|
<Compile Include="Models\SchedulerModel.cs" />
|
||||||
|
<Compile Include="Util\BeWoLoginState.cs" />
|
||||||
<Compile Include="Util\GoalTreeItem.cs" />
|
<Compile Include="Util\GoalTreeItem.cs" />
|
||||||
<Compile Include="Controllers\LoginController.cs" />
|
<Compile Include="Controllers\LoginController.cs" />
|
||||||
<Compile Include="Controllers\MainController.cs" />
|
<Compile Include="Controllers\MainController.cs" />
|
||||||
|
|||||||
@@ -401,7 +401,7 @@ ul {
|
|||||||
right:0;
|
right:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#popupDiv, #errorPopupDiv, #SuccessPopupDiv, #AendernPopupDiv, #validationPopupDiv {
|
#popupDiv, #errorPopupDiv, #SuccessPopupDiv, #AendernPopupDiv, #validationPopupDiv, #loginStatePopupDiv {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
height: 20%;
|
height: 20%;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using BS.Shared.DataContracts;
|
|||||||
namespace BeWoPlanerMobil.Controllers
|
namespace BeWoPlanerMobil.Controllers
|
||||||
{
|
{
|
||||||
public abstract class AbstractBaseController : Controller
|
public abstract class AbstractBaseController : Controller
|
||||||
{
|
{
|
||||||
protected readonly ICustomerService CustomerService = new MobileSessionFacade().CustomerService;
|
protected readonly ICustomerService CustomerService = new MobileSessionFacade().CustomerService;
|
||||||
protected readonly IOperationsService OperationsService = new MobileSessionFacade().OperationsService;
|
protected readonly IOperationsService OperationsService = new MobileSessionFacade().OperationsService;
|
||||||
protected readonly IEmployeeService EmployeeService = new MobileSessionFacade().EmployeeService;
|
protected readonly IEmployeeService EmployeeService = new MobileSessionFacade().EmployeeService;
|
||||||
@@ -18,7 +18,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
protected readonly IUserService UserService = new MobileSessionFacade().UserService;
|
protected readonly IUserService UserService = new MobileSessionFacade().UserService;
|
||||||
protected const string _LeerzeichenFuerGetMethoden = " ";
|
protected const string _LeerzeichenFuerGetMethoden = " ";
|
||||||
|
|
||||||
protected static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
protected static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
protected ActionResult Logout()
|
protected ActionResult Logout()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
log.Error(exception.Message, exception);
|
Log.Error(exception.Message, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RedirectToActionPermanent("Customer");
|
return RedirectToActionPermanent("Customer");
|
||||||
@@ -192,7 +192,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
log.Error(exception.Message, exception);
|
Log.Error(exception.Message, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RedirectToActionPermanent("PreselectCustomer", new {customerOid = Model.SelectedCustomerOid});
|
return RedirectToActionPermanent("PreselectCustomer", new {customerOid = Model.SelectedCustomerOid});
|
||||||
|
|||||||
@@ -5,9 +5,12 @@ using System.Web.Mvc;
|
|||||||
using System.Web.Security;
|
using System.Web.Security;
|
||||||
|
|
||||||
using BeWoPlanerMobil.Service;
|
using BeWoPlanerMobil.Service;
|
||||||
|
using BeWoPlanerMobil.Util;
|
||||||
using BS.Shared;
|
using BS.Shared;
|
||||||
using BS.Shared.DataContracts;
|
using BS.Shared.DataContracts;
|
||||||
|
using RestSharp;
|
||||||
|
using HttpCookie = System.Web.HttpCookie;
|
||||||
|
|
||||||
|
|
||||||
namespace BeWoPlanerMobil.Controllers
|
namespace BeWoPlanerMobil.Controllers
|
||||||
{
|
{
|
||||||
@@ -21,13 +24,22 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
ViewData[LoginErrorIndex] = string.Empty;
|
ViewData[LoginErrorIndex] = string.Empty;
|
||||||
|
|
||||||
if (MobileSessionFacade.IsUserLoggedIn() && !Request.Browser.Browser.Equals("InternetExplorer"))
|
if (MobileSessionFacade.IsUserLoggedIn() && !Request.Browser.Browser.Equals("InternetExplorer"))
|
||||||
{
|
{
|
||||||
log.Info($"LoginController.Index(): Loggedin User: {MobileSessionFacade.LoggedInUser.LoginName}");
|
var loginState = MobileUtils.GetLoginState(MobileSessionFacade.Tenant);
|
||||||
|
|
||||||
|
if (loginState.Message != null && loginState.State > -1)
|
||||||
|
{
|
||||||
|
TempData[MobileUtils.TempDataLoginStateKey] = loginState;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Info($"LoginController.Index(): Loggedin User: {MobileSessionFacade.LoggedInUser.LoginName}");
|
||||||
|
|
||||||
if (!MobileSessionFacade.LoggedInUser.UserGroups.Any(a => a.Rights.Any(f => f.RightType.Equals(UserRightType.ServiceRecordView_View))) &&
|
if (!MobileSessionFacade.LoggedInUser.UserGroups.Any(a => a.Rights.Any(f => f.RightType.Equals(UserRightType.ServiceRecordView_View))) &&
|
||||||
!MobileSessionFacade.LoggedInUser.UserGroups.Any(a => a.Rights.Any(f => f.RightType.Equals(UserRightType.ViewAll))))
|
!MobileSessionFacade.LoggedInUser.UserGroups.Any(a => a.Rights.Any(f => f.RightType.Equals(UserRightType.ViewAll))))
|
||||||
{
|
{
|
||||||
ViewData[LoginErrorIndex] = HttpUtility.HtmlDecode("Sie haben keine ausreichenden Berechtigungen, um die Zeiterfassung anzeigen zu lassen.");
|
ViewData[LoginErrorIndex] = HttpUtility.HtmlDecode("Sie haben keine ausreichenden Berechtigungen, um die Zeiterfassung anzeigen zu lassen.");
|
||||||
|
MobileSessionFacade.LogUserOut();
|
||||||
|
FormsAuthentication.SignOut();
|
||||||
return View("Index");
|
return View("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +70,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
FormsAuthentication.SignOut();
|
FormsAuthentication.SignOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info($"LoginController.Index(): Login failed! Tenant = {MobileSessionFacade.Tenant}");
|
Log.Info($"LoginController.Index(): Login failed! Tenant = {MobileSessionFacade.Tenant}");
|
||||||
|
|
||||||
ViewData[LoginErrorIndex] = Request.Browser.Browser.Equals("InternetExplorer") ?
|
ViewData[LoginErrorIndex] = Request.Browser.Browser.Equals("InternetExplorer") ?
|
||||||
"Dieser Browser ist nicht mit dem mobilen BeWoPlaner komptatibel. Bitte benutzen Sie einen anderen Browser als den Internet Explorer." :
|
"Dieser Browser ist nicht mit dem mobilen BeWoPlaner komptatibel. Bitte benutzen Sie einen anderen Browser als den Internet Explorer." :
|
||||||
@@ -86,7 +98,14 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
|
|
||||||
if (MobileSessionFacade.IsUserLoggedIn())
|
if (MobileSessionFacade.IsUserLoggedIn())
|
||||||
{
|
{
|
||||||
return RedirectToActionPermanent("Main", "Main");
|
//https://support.bewoplaner.de/api/getstate.php?k=[KUNDENNUMMER]&type=1
|
||||||
|
|
||||||
|
var baseUrl = "https://support.bewoplaner.de/api/getstate.php";
|
||||||
|
|
||||||
|
var client = new RestClient(baseUrl);
|
||||||
|
var request = new RestRequest();
|
||||||
|
|
||||||
|
return RedirectToActionPermanent("Main", "Main");
|
||||||
}
|
}
|
||||||
|
|
||||||
MobileSessionFacade.Tenant = tenant;
|
MobileSessionFacade.Tenant = tenant;
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
{
|
{
|
||||||
ViewData["ValidationError"] = string.Empty;
|
ViewData["ValidationError"] = string.Empty;
|
||||||
|
|
||||||
|
var value = TempData[TempDataLoginStateKey];
|
||||||
|
|
||||||
if(!MobileSessionFacade.IsUserLoggedIn() || Request.Browser.Browser.Equals("InternetExplorer"))
|
if(!MobileSessionFacade.IsUserLoggedIn() || Request.Browser.Browser.Equals("InternetExplorer"))
|
||||||
{
|
{
|
||||||
return RedirectToActionPermanent("Index", "Login");
|
return RedirectToActionPermanent("Index", "Login");
|
||||||
@@ -187,7 +189,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return View(Model);
|
return View(Model);
|
||||||
@@ -472,7 +474,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
return SerializeObject("Fehler 560");
|
return SerializeObject("Fehler 560");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -509,7 +511,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
return SerializeObject("Fehler 540");
|
return SerializeObject("Fehler 540");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -564,7 +566,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
log.Error(exception.Message, exception);
|
Log.Error(exception.Message, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
@@ -586,7 +588,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
return SerializeObject("Fehler 777: Fail Error Compilation");
|
return SerializeObject("Fehler 777: Fail Error Compilation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -698,7 +700,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
return SerializeObject("Fehler 777: Fail Error Compilation");
|
return SerializeObject("Fehler 777: Fail Error Compilation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -725,7 +727,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
doku1 = collection["Dokumentation6"];
|
doku1 = collection["Dokumentation6"];
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info($"CreateServiceRecord: datum:{collection["Datum"]}; start:{collection["Start"]}; ende:{collection["Ende"]}; dauer:{collection["Dauer"]}; doku:{doku1}; aktion:{collection["versteckt"]}");
|
Log.Info($"CreateServiceRecord: datum:{collection["Datum"]}; start:{collection["Start"]}; ende:{collection["Ende"]}; dauer:{collection["Dauer"]}; doku:{doku1}; aktion:{collection["versteckt"]}");
|
||||||
|
|
||||||
if(string.IsNullOrEmpty(collection["Datum"]))
|
if(string.IsNullOrEmpty(collection["Datum"]))
|
||||||
{
|
{
|
||||||
@@ -918,7 +920,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Model.SaveSignature = Model.ShowSignature && Model.SelectedSupportConcept != null;
|
Model.SaveSignature = Model.ShowSignature && Model.SelectedSupportConcept != null;
|
||||||
@@ -1339,7 +1341,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
return RedirectToActionPermanent("Index", "Login");
|
return RedirectToActionPermanent("Index", "Login");
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info($"saveZeiterfassungAfterCrash: datum:{pDatum};start:{pStartDate};ende:{pEndDate};dauer:{pDuration};doku:{pNotice};doku2:{pNotice2};doku3:{pNotice3};doku4:{pNotice4};doku5:{pNotice5};pEndDate2:{pEndDate2}");
|
Log.Info($"saveZeiterfassungAfterCrash: datum:{pDatum};start:{pStartDate};ende:{pEndDate};dauer:{pDuration};doku:{pNotice};doku2:{pNotice2};doku3:{pNotice3};doku4:{pNotice4};doku5:{pNotice5};pEndDate2:{pEndDate2}");
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(pDatum))
|
if (string.IsNullOrEmpty(pDatum))
|
||||||
{
|
{
|
||||||
@@ -1490,7 +1492,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
Model.ErrorWert = 2;
|
Model.ErrorWert = 2;
|
||||||
//log.Error(e.Message, e);
|
//log.Error(e.Message, e);
|
||||||
}
|
}
|
||||||
@@ -1810,7 +1812,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
return _LeerzeichenFuerGetMethoden;
|
return _LeerzeichenFuerGetMethoden;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info($"CheckRights: von:{von};bis:{bis};inEditMode:{inEditMode};dateString:{dateString};startString:{startString};endString:{endString}");
|
Log.Info($"CheckRights: von:{von};bis:{bis};inEditMode:{inEditMode};dateString:{dateString};startString:{startString};endString:{endString}");
|
||||||
|
|
||||||
var startHoursDt = ConvertTimeStringToDateTime(startString);
|
var startHoursDt = ConvertTimeStringToDateTime(startString);
|
||||||
var endHoursDt = ConvertTimeStringToDateTime(endString);
|
var endHoursDt = ConvertTimeStringToDateTime(endString);
|
||||||
@@ -2085,7 +2087,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info($"CheckRightsAfterCrash: von:{von};bis:{bis};inEditMode:{inEditMode};dateString:{dateString};startString:{startString};endString:{endString}");
|
Log.Info($"CheckRightsAfterCrash: von:{von};bis:{bis};inEditMode:{inEditMode};dateString:{dateString};startString:{startString};endString:{endString}");
|
||||||
|
|
||||||
var date = DateTime.Now.Date;
|
var date = DateTime.Now.Date;
|
||||||
|
|
||||||
@@ -2230,15 +2232,15 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Info("Error in SetServiceRecordEmployee:");
|
Log.Info("Error in SetServiceRecordEmployee:");
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
if (MainModel.AllEmployees == null)
|
if (MainModel.AllEmployees == null)
|
||||||
{
|
{
|
||||||
log.Info("Weitere Infos: AllEmployees = null!");
|
Log.Info("Weitere Infos: AllEmployees = null!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log.Info($"Weitere Infos: AllEmployees enthält {MainModel.AllEmployees.Count} Elemente: ");
|
Log.Info($"Weitere Infos: AllEmployees enthält {MainModel.AllEmployees.Count} Elemente: ");
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
foreach (var ce in MainModel.AllEmployees)
|
foreach (var ce in MainModel.AllEmployees)
|
||||||
{
|
{
|
||||||
@@ -2251,7 +2253,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
sb.Append(ce.EmployeeOid);
|
sb.Append(ce.EmployeeOid);
|
||||||
|
|
||||||
}
|
}
|
||||||
log.Info(sb.ToString());
|
Log.Info(sb.ToString());
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
return SerializeObject("Fehler 510");
|
return SerializeObject("Fehler 510");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
return SerializeObject("Fehler 550: Internal Server Error");
|
return SerializeObject("Fehler 550: Internal Server Error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,7 +241,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
SerializeObject("Fehler 520");
|
SerializeObject("Fehler 520");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,7 +266,7 @@ namespace BeWoPlanerMobil.Controllers
|
|||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.Error(e.Message, e);
|
Log.Error(e.Message, e);
|
||||||
return SerializeObject("Fehler 530");
|
return SerializeObject("Fehler 530");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace BeWoPlanerMobil
|
|||||||
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
|
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
|
||||||
// visit http://go.microsoft.com/?LinkId=9394801
|
// visit http://go.microsoft.com/?LinkId=9394801
|
||||||
|
|
||||||
public class MvcApplication : System.Web.HttpApplication
|
public class MvcApplication : HttpApplication
|
||||||
{
|
{
|
||||||
protected void Application_Start()
|
protected void Application_Start()
|
||||||
{
|
{
|
||||||
@@ -21,7 +21,6 @@ namespace BeWoPlanerMobil
|
|||||||
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
|
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
|
||||||
RouteConfig.RegisterRoutes(RouteTable.Routes);
|
RouteConfig.RegisterRoutes(RouteTable.Routes);
|
||||||
BundleConfig.RegisterBundles(BundleTable.Bundles);
|
BundleConfig.RegisterBundles(BundleTable.Bundles);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Application_BeginRequest(object sender, EventArgs e)
|
protected void Application_BeginRequest(object sender, EventArgs e)
|
||||||
|
|||||||
@@ -54,5 +54,8 @@ namespace BeWoPlanerMobil.Models
|
|||||||
public string TabControlDisplayValue => SelectedJsonCustomer != null ? "block" : "none";
|
public string TabControlDisplayValue => SelectedJsonCustomer != null ? "block" : "none";
|
||||||
|
|
||||||
public int SelectedCustomerTab { get; set; }
|
public int SelectedCustomerTab { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
// NewVM ähnlich wie im
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,16 +5,10 @@ namespace BeWoPlanerMobil.Models
|
|||||||
{
|
{
|
||||||
public class LoginModel
|
public class LoginModel
|
||||||
{
|
{
|
||||||
public static String Tenant
|
public static string Tenant
|
||||||
{
|
{
|
||||||
get
|
get => MobileSessionFacade.Tenant;
|
||||||
{
|
set => MobileSessionFacade.Tenant = value;
|
||||||
return MobileSessionFacade.Tenant;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
MobileSessionFacade.Tenant = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -508,7 +508,9 @@ function toggleErrorPopup(errorMessage, i) {
|
|||||||
$(".modalWrapper").css("height", $(document).height());
|
$(".modalWrapper").css("height", $(document).height());
|
||||||
|
|
||||||
if(isDisplayNone ) {
|
if(isDisplayNone ) {
|
||||||
$("#errorPopupText").text(errorMessage);
|
if(i !== 3){
|
||||||
|
$("#errorPopupText").text(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
if(i === 1) {
|
if(i === 1) {
|
||||||
$("#errorPopupTitle").text("Info");
|
$("#errorPopupTitle").text("Info");
|
||||||
@@ -520,6 +522,12 @@ function toggleErrorPopup(errorMessage, i) {
|
|||||||
clearLocalStorage(1);
|
clearLocalStorage(1);
|
||||||
//SaveOnly(); // Speichere Daten bei absturz
|
//SaveOnly(); // Speichere Daten bei absturz
|
||||||
}
|
}
|
||||||
|
else if (i === 3) {
|
||||||
|
$("#errorPopupText").text("");
|
||||||
|
$("#errorPopupContentDiv").html(errorMessage);
|
||||||
|
$("#errorPopupTitle").text("Info");
|
||||||
|
$("#errorPopupOkBtn").onclick = "toggleErrorPopup('')";
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
$("#errorPopupTitle").text("Fehler");
|
$("#errorPopupTitle").text("Fehler");
|
||||||
$("#errorPopupOkBtn").onclick = "toggleErrorPopup('')";
|
$("#errorPopupOkBtn").onclick = "toggleErrorPopup('')";
|
||||||
@@ -529,8 +537,9 @@ function toggleErrorPopup(errorMessage, i) {
|
|||||||
var errorPopupTextOuterHeight = $("#errorPopupText").outerHeight();
|
var errorPopupTextOuterHeight = $("#errorPopupText").outerHeight();
|
||||||
var errorPopupButtonOuterHeight = $("#errorPopupBtnDiv").outerHeight();
|
var errorPopupButtonOuterHeight = $("#errorPopupBtnDiv").outerHeight();
|
||||||
var errorPopupOkButtonOuterHeight = $("#errorPopupOkBtn").outerHeight();
|
var errorPopupOkButtonOuterHeight = $("#errorPopupOkBtn").outerHeight();
|
||||||
|
var errorPopupContentDivOuterHeight = $("#errorPopupContentDiv").outerHeight();
|
||||||
|
|
||||||
var height = errorPopupTitleOuterHeight + errorPopupTextOuterHeight + errorPopupButtonOuterHeight + errorPopupOkButtonOuterHeight + errorPopupOkButtonOuterHeight;
|
var height = errorPopupTitleOuterHeight + errorPopupTextOuterHeight + errorPopupButtonOuterHeight + errorPopupOkButtonOuterHeight + errorPopupOkButtonOuterHeight + errorPopupContentDivOuterHeight;
|
||||||
|
|
||||||
$("#errorPopupDiv").css("height", height + "px");
|
$("#errorPopupDiv").css("height", height + "px");
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.ServiceModel;
|
using System.ServiceModel;
|
||||||
@@ -31,7 +32,7 @@ namespace BeWoPlanerMobil.Service
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Monitor.Enter(_Lock);
|
Monitor.Enter(_Lock);
|
||||||
|
|
||||||
if (!_SessionFactories.ContainsKey(MobileSessionFacade.Tenant))
|
if (!_SessionFactories.ContainsKey(MobileSessionFacade.Tenant))
|
||||||
@@ -43,7 +44,7 @@ namespace BeWoPlanerMobil.Service
|
|||||||
|
|
||||||
if (!File.Exists(serverPath))
|
if (!File.Exists(serverPath))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_SessionFactories[MobileSessionFacade.Tenant] = new Configuration().Configure(serverPath).SetInterceptor(new MobileUpdInsInterceptor()).BuildSessionFactory();
|
_SessionFactories[MobileSessionFacade.Tenant] = new Configuration().Configure(serverPath).SetInterceptor(new MobileUpdInsInterceptor()).BuildSessionFactory();
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ namespace BeWoPlanerMobil.Service
|
|||||||
UserService = new UserServiceImp();
|
UserService = new UserServiceImp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICustomerService CustomerService { get; private set; }
|
public ICustomerService CustomerService { get; }
|
||||||
public IEmployeeService EmployeeService { get; private set; }
|
public IEmployeeService EmployeeService { get; }
|
||||||
public IOperationsService OperationsService { get; private set; }
|
public IOperationsService OperationsService { get; }
|
||||||
public IValueListService ValueListService { get; private set; }
|
public IValueListService ValueListService { get; }
|
||||||
public ResourceServiceImp ResourceService { get; private set; }
|
public ResourceServiceImp ResourceService { get; }
|
||||||
public IAnalysisService AnalysisService { get; private set; }
|
public IAnalysisService AnalysisService { get; }
|
||||||
public IUserService UserService { get; private set; }
|
public IUserService UserService { get; }
|
||||||
|
|
||||||
public static ApplicationUser LoggedInUser
|
public static ApplicationUser LoggedInUser
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using BeWo.Data;
|
|
||||||
using BeWo.Data.Entities;
|
using BeWo.Data.Entities;
|
||||||
|
|
||||||
using BS.Shared.Extensions;
|
using BS.Shared.Extensions;
|
||||||
@@ -18,7 +17,7 @@ namespace BeWoPlanerMobil.Service
|
|||||||
{
|
{
|
||||||
if (MobileSessionFacade.IsUserLoggedIn())
|
if (MobileSessionFacade.IsUserLoggedIn())
|
||||||
{
|
{
|
||||||
currentState[i] = String.Format("{0}", MobileSessionFacade.EmployeeFullname);
|
currentState[i] = $"{MobileSessionFacade.EmployeeFullname}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -36,13 +35,13 @@ namespace BeWoPlanerMobil.Service
|
|||||||
var i = propertyNames.IndexOf(BeWoEntityBase.PropertyName_InsUser);
|
var i = propertyNames.IndexOf(BeWoEntityBase.PropertyName_InsUser);
|
||||||
if (i >= 0)
|
if (i >= 0)
|
||||||
{
|
{
|
||||||
state[i] = string.Format("{0}", MobileSessionFacade.EmployeeFullname);
|
state[i] = $"{MobileSessionFacade.EmployeeFullname}";
|
||||||
}
|
}
|
||||||
|
|
||||||
i = propertyNames.IndexOf(BeWoEntityBase.PropertyName_UdpUser);
|
i = propertyNames.IndexOf(BeWoEntityBase.PropertyName_UdpUser);
|
||||||
if (i >= 0)
|
if (i >= 0)
|
||||||
{
|
{
|
||||||
state[i] = string.Format("{0}", MobileSessionFacade.EmployeeFullname);
|
state[i] = $"{MobileSessionFacade.EmployeeFullname}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using System.ComponentModel;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
using System.Web.Services;
|
using System.Web.Services;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
using BeWo.Data;
|
using BeWo.Data;
|
||||||
using BeWo.Data.Access;
|
using BeWo.Data.Access;
|
||||||
using BeWo.Service.ServiceContracts;
|
using BeWo.Service.ServiceContracts;
|
||||||
@@ -10,6 +13,7 @@ using BS.Shared;
|
|||||||
using BS.Shared.Core;
|
using BS.Shared.Core;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using ASPHibernateSessionManager = BeWoPlanerMobil.Service.ASPHibernateSessionManager;
|
using ASPHibernateSessionManager = BeWoPlanerMobil.Service.ASPHibernateSessionManager;
|
||||||
|
using Formatting = Newtonsoft.Json.Formatting;
|
||||||
|
|
||||||
namespace BeWoPlanerMobil
|
namespace BeWoPlanerMobil
|
||||||
{
|
{
|
||||||
@@ -17,7 +21,7 @@ namespace BeWoPlanerMobil
|
|||||||
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
|
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
|
||||||
[ToolboxItem(false)]
|
[ToolboxItem(false)]
|
||||||
// Wenn der Aufruf dieses Webdiensts aus einem Skript mithilfe von ASP.NET AJAX zulässig sein soll, heben Sie die Kommentarmarkierung für die folgende Zeile auf.
|
// Wenn der Aufruf dieses Webdiensts aus einem Skript mithilfe von ASP.NET AJAX zulässig sein soll, heben Sie die Kommentarmarkierung für die folgende Zeile auf.
|
||||||
// [System.Web.Script.Services.ScriptService]
|
[System.Web.Script.Services.ScriptService]
|
||||||
public class TestWebService : WebService
|
public class TestWebService : WebService
|
||||||
{
|
{
|
||||||
protected readonly ICustomerService CustomerService = new MobileSessionFacade().CustomerService;
|
protected readonly ICustomerService CustomerService = new MobileSessionFacade().CustomerService;
|
||||||
@@ -25,10 +29,11 @@ namespace BeWoPlanerMobil
|
|||||||
protected readonly IEmployeeService EmployeeService = new MobileSessionFacade().EmployeeService;
|
protected readonly IEmployeeService EmployeeService = new MobileSessionFacade().EmployeeService;
|
||||||
|
|
||||||
[WebMethod(EnableSession = true)]
|
[WebMethod(EnableSession = true)]
|
||||||
public void TestLogin(string pUserName, string pPassword)
|
public bool TestLogin(string pUserName, string pPassword, string pTenant)
|
||||||
{
|
{
|
||||||
MobileSessionFacade.Tenant = "demo";
|
var result = false;
|
||||||
SessionFacade.Tenant = "demo";
|
MobileSessionFacade.Tenant = pTenant;
|
||||||
|
SessionFacade.Tenant = pTenant;
|
||||||
|
|
||||||
ASPHibernateSessionManager.ConfigureHibernateSessionForWebService();
|
ASPHibernateSessionManager.ConfigureHibernateSessionForWebService();
|
||||||
|
|
||||||
@@ -40,11 +45,17 @@ namespace BeWoPlanerMobil
|
|||||||
|
|
||||||
if(user == null || !DAOFactory.UserDAO.CheckPassword(user, pPassword))
|
if(user == null || !DAOFactory.UserDAO.CheckPassword(user, pPassword))
|
||||||
{
|
{
|
||||||
return;
|
result = false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MobileSessionFacade.LoggedInUser = user;
|
||||||
|
|
||||||
MobileSessionFacade.LoggedInUser = user;
|
result = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[WebMethod(EnableSession = true)]
|
[WebMethod(EnableSession = true)]
|
||||||
@@ -59,9 +70,31 @@ namespace BeWoPlanerMobil
|
|||||||
return SerializeObject(result);
|
return SerializeObject(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[WebMethod(EnableSession = true)]
|
||||||
|
public string TestMitFehler()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Das ist nur eine Testausnahme!");
|
||||||
|
}
|
||||||
|
|
||||||
private static string SerializeObject(object obj)
|
private static string SerializeObject(object obj)
|
||||||
{
|
{
|
||||||
return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
|
return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string SerializeObjectToXml<T>(object obj)
|
||||||
|
{
|
||||||
|
var result = string.Empty;
|
||||||
|
|
||||||
|
var xmlSerializer = new XmlSerializer(typeof(T));
|
||||||
|
var stringWriter = new StringWriter();
|
||||||
|
|
||||||
|
using (var xmlWriter = XmlWriter.Create(stringWriter))
|
||||||
|
{
|
||||||
|
xmlSerializer.Serialize(xmlWriter, obj);
|
||||||
|
result = stringWriter.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
BeWoPlanerMobil/Util/BeWoLoginState.cs
Normal file
14
BeWoPlanerMobil/Util/BeWoLoginState.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace BeWoPlanerMobil.Util
|
||||||
|
{
|
||||||
|
public class BeWoLoginState
|
||||||
|
{
|
||||||
|
public int State { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
public BeWoLoginState(int state, string message)
|
||||||
|
{
|
||||||
|
State = state;
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using BeWoPlanerMobil.Models;
|
using BeWoPlanerMobil.Models;
|
||||||
|
|
||||||
using BS.Shared.Core;
|
using BS.Shared.Core;
|
||||||
@@ -13,7 +13,7 @@ using BS.Shared.Extensions;
|
|||||||
using DevExpress.XtraScheduler;
|
using DevExpress.XtraScheduler;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using RestSharp;
|
||||||
using static System.Int32;
|
using static System.Int32;
|
||||||
using static System.String;
|
using static System.String;
|
||||||
|
|
||||||
@@ -21,6 +21,8 @@ namespace BeWoPlanerMobil.Util
|
|||||||
{
|
{
|
||||||
public class MobileUtils
|
public class MobileUtils
|
||||||
{
|
{
|
||||||
|
public static string TempDataLoginStateKey => "loginstate";
|
||||||
|
|
||||||
public static DateTime ConvertTimeStringToDateTime(string timeString)
|
public static DateTime ConvertTimeStringToDateTime(string timeString)
|
||||||
{
|
{
|
||||||
var dt = DateTime.Now.Date;
|
var dt = DateTime.Now.Date;
|
||||||
@@ -40,7 +42,7 @@ namespace BeWoPlanerMobil.Util
|
|||||||
}
|
}
|
||||||
while (numberString.Length < 4)
|
while (numberString.Length < 4)
|
||||||
{
|
{
|
||||||
numberString = numberString + "0";
|
numberString += "0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -105,9 +107,8 @@ namespace BeWoPlanerMobil.Util
|
|||||||
var startDate = datum;
|
var startDate = datum;
|
||||||
var endDate = enddatum;
|
var endDate = enddatum;
|
||||||
|
|
||||||
var h = 0;
|
const int hours = 0;
|
||||||
var m = 0;
|
const int minutes = 0;
|
||||||
|
|
||||||
|
|
||||||
var dateStartTime = ConvertTimeStringToDateTime(start);
|
var dateStartTime = ConvertTimeStringToDateTime(start);
|
||||||
startDate = startDate.AddHours(dateStartTime.Hour).AddMinutes(dateStartTime.Minute);
|
startDate = startDate.AddHours(dateStartTime.Hour).AddMinutes(dateStartTime.Minute);
|
||||||
@@ -115,10 +116,8 @@ namespace BeWoPlanerMobil.Util
|
|||||||
var dateEndTime = ConvertTimeStringToDateTime(ende);
|
var dateEndTime = ConvertTimeStringToDateTime(ende);
|
||||||
endDate = endDate.AddHours(dateEndTime.Hour).AddMinutes(dateEndTime.Minute);
|
endDate = endDate.AddHours(dateEndTime.Hour).AddMinutes(dateEndTime.Minute);
|
||||||
|
|
||||||
|
endDate = endDate.AddHours(hours);
|
||||||
|
endDate = endDate.AddMinutes(minutes);
|
||||||
endDate = endDate.AddHours(h);
|
|
||||||
endDate = endDate.AddMinutes(m);
|
|
||||||
|
|
||||||
if (IsNullOrEmpty(start) && !IsNullOrEmpty(ende))
|
if (IsNullOrEmpty(start) && !IsNullOrEmpty(ende))
|
||||||
{
|
{
|
||||||
@@ -217,7 +216,7 @@ namespace BeWoPlanerMobil.Util
|
|||||||
return GetDecimalValue(decValue, decCount);
|
return GetDecimalValue(decValue, decCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return decValue;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JSONCustomer GetJSONCustomer(CustomerDC pCustomer)
|
public static JSONCustomer GetJSONCustomer(CustomerDC pCustomer)
|
||||||
@@ -234,12 +233,12 @@ namespace BeWoPlanerMobil.Util
|
|||||||
{
|
{
|
||||||
catOid2ModelDict[sd.Category.ServiceCategoryOid.Value] = new ServiceCategoryModel
|
catOid2ModelDict[sd.Category.ServiceCategoryOid.Value] = new ServiceCategoryModel
|
||||||
{
|
{
|
||||||
Name = sd.Category.Name,
|
Name = sd.Category.Name,
|
||||||
IsDefault = sd.Category.IsDefault,
|
IsDefault = sd.Category.IsDefault,
|
||||||
Percentage = sd.Category.Percentage,
|
Percentage = sd.Category.Percentage,
|
||||||
Position = sd.Category.Position,
|
Position = sd.Category.Position,
|
||||||
OhneHilfeplan = sd.Category.OhneHilfeplan,
|
OhneHilfeplan = sd.Category.OhneHilfeplan,
|
||||||
ServiceCategoryOid = sd.Category.ServiceCategoryOid,
|
ServiceCategoryOid = sd.Category.ServiceCategoryOid,
|
||||||
ServiceDescriptions = new List<ServiceDescriptionDC>()
|
ServiceDescriptions = new List<ServiceDescriptionDC>()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -378,5 +377,43 @@ namespace BeWoPlanerMobil.Util
|
|||||||
{
|
{
|
||||||
return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
|
return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BeWoLoginState GetLoginState(string tenant)
|
||||||
|
{
|
||||||
|
var result = new BeWoLoginState(-1, null);
|
||||||
|
|
||||||
|
const string baseUrl = "https://support.bewoplaner.de/api";
|
||||||
|
const string resource = "getstate.php";
|
||||||
|
|
||||||
|
var client = new RestClient(baseUrl);
|
||||||
|
|
||||||
|
var request = new RestRequest(resource, Method.GET);
|
||||||
|
|
||||||
|
request.AddParameter("k", tenant, ParameterType.QueryString);
|
||||||
|
request.AddParameter("type", 1, ParameterType.QueryString);
|
||||||
|
|
||||||
|
var response = client.Execute(request);
|
||||||
|
|
||||||
|
return response.Content != null ? DeserializeLoginState(response.Content) : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BeWoLoginState DeserializeLoginState(string state)
|
||||||
|
{
|
||||||
|
var responseState = -1;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(state) || !state.Contains(';'))
|
||||||
|
{
|
||||||
|
return new BeWoLoginState(responseState, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var arr = state.Split(';');
|
||||||
|
|
||||||
|
var message = arr[0].Replace("\n", "<br />");
|
||||||
|
var isSuccessful = int.TryParse(arr[1], out var convertedResponseState);
|
||||||
|
|
||||||
|
responseState = isSuccessful ? convertedResponseState : -1;
|
||||||
|
|
||||||
|
return new BeWoLoginState(responseState, message.Replace("\\", "\\\\"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,208 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="input-wrapper" style="display: @Model.TabControlDisplayValue;">
|
<div id="klienten" style="display: @Model.TabControlDisplayValue; margin-left: .5em; margin-right: .5em;">
|
||||||
|
<div id="klientenTabelle">
|
||||||
|
<div class="eigenschaftsdiv">
|
||||||
|
<h4>Eigenschaften</h4>
|
||||||
|
<hr />
|
||||||
|
<table class="width-inheriting-table">
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Vorname:</td>
|
||||||
|
<td class="contentTd">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Vorname : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Nachname:</td>
|
||||||
|
<td class="contentTd" id="KlientNachname">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Nachname : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Geburtstag:</td>
|
||||||
|
<td class="contentTd" id="KlientGeb">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Geburtstag : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Geschlecht:</td>
|
||||||
|
<td class="contentTd" id="KlientSex">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Geschlecht : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="eigenschaftsdiv">
|
||||||
|
<h4 class="inline-display-element">Adresse</h4>
|
||||||
|
<input type="button" onclick="karteAnzeigen()" style="background-image: url(@Url.Content("~/Content/images/location-orange.svg")); background-repeat: no-repeat; background-position: center; background-size: 55%; background-color: transparent; margin-top: -0.6em; display: inline; width: auto; float: right;" />
|
||||||
|
<hr />
|
||||||
|
<table class="width-inheriting-table">
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Adresszusatz:</td>
|
||||||
|
<td class="contentTd" id="KlientAdresse">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Adresszusatz : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Straße:</td>
|
||||||
|
<td class="contentTd" id="adressfeld">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Strasse : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">PLZ:</td>
|
||||||
|
<td class="contentTd" id="plzfeld">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Postleitzahl : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Ort:</td>
|
||||||
|
<td class="contentTd" id="ortfeld">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Ort : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="eigenschaftsdiv">
|
||||||
|
<h4>Rechnungsadresse</h4>
|
||||||
|
<hr />
|
||||||
|
<table class="width-inheriting-table">
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Name:</td>
|
||||||
|
<td class="contentTd" id="KlientReName">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.RechnungsadresseName : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Straße:</td>
|
||||||
|
<td class="contentTd" id="KlientReStrasse">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.RechnungsadresseStrasse : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Postleitzahl:</td>
|
||||||
|
<td class="contentTd" id="KlientRePostleitzahl">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.RechnungsadressePostleitzahl : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Ort:</td>
|
||||||
|
<td class="contentTd" id="KlientReOrt">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.RechnungsadresseOrt : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="eigenschaftsdiv">
|
||||||
|
<h4>Kontakt</h4>
|
||||||
|
<hr />
|
||||||
|
<table class="width-inheriting-table">
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Handy:</td>
|
||||||
|
<td class="contentTd" id="KlientHandy">
|
||||||
|
<a style="color: black" href="@Html.Raw(Model.SelectedJsonCustomer != null ? "tel:" + Model.SelectedJsonCustomer.Handy : string.Empty)">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Handy : string.Empty)</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Telefon:</td>
|
||||||
|
<td class="contentTd" id="KlientTelefon">
|
||||||
|
<a style="color: black" href="@Html.Raw(Model.SelectedJsonCustomer != null ? "tel:" + Model.SelectedJsonCustomer.Telefon : string.Empty)">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Telefon : string.Empty)</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Fax:</td>
|
||||||
|
<td class="contentTd" id="KlientFax">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.Fax : string.Empty)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="customer-td">Mail:</td>
|
||||||
|
<td class="contentTd" id="KlientMail"><a style="color: black" href="@Html.Raw(Model.SelectedJsonCustomer != null ? "mailto:" + Model.SelectedJsonCustomer.EMail : string.Empty)">@Html.Raw(Model.SelectedJsonCustomer != null ? Model.SelectedJsonCustomer.EMail : string.Empty)</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px; display: @Model.ReferenceNumberDisplayValue" id="aktenzeichenContainer">
|
||||||
|
<h4 style="display: inline; color: #AB4A07;">Aktenzeichen pro Kostenträger</h4>
|
||||||
|
<hr />
|
||||||
|
<table id="aktenzeichenTable" class="width-inheriting-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">
|
||||||
|
<p style="float: left;">Kostenträger</p>
|
||||||
|
</th>
|
||||||
|
<th scope="col">
|
||||||
|
<p style="float: right;">Aktenzeichen</p>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@if (Model.SelectedJsonCustomer != null)
|
||||||
|
{
|
||||||
|
foreach (var referenceNumber in Model.SelectedJsonCustomer.ReferenceNumbers)
|
||||||
|
{
|
||||||
|
<tr class="testklasse">
|
||||||
|
<td class="customer-td">@referenceNumber.Costbearer</td>
|
||||||
|
<td class="contentTd">@referenceNumber.ReferenceNumber</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="testklasse">
|
||||||
|
<td colspan="2"><hr /></td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: @Model.NoticeDisplayValue" id="kommentarContainer">
|
||||||
|
<h4 style="display: inline; color: #AB4A07;">Kommentar</h4>
|
||||||
|
<hr />
|
||||||
|
<pre>
|
||||||
|
@if (Model.SelectedJsonCustomer != null)
|
||||||
|
{
|
||||||
|
@Html.Raw(Model.SelectedJsonCustomer.Kommentar)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: @Model.EnvironmentPersonsDisplayValue" id="umfeldContainer">
|
||||||
|
<h4 style="display: inline; color: #AB4A07;">Umfeld</h4>
|
||||||
|
<hr />
|
||||||
|
<div style="width: inherit; padding-bottom: .5em;">
|
||||||
|
@if (Model.SelectedJsonCustomer != null)
|
||||||
|
{
|
||||||
|
foreach (var relatedPerson in Model.SelectedJsonCustomer.Umfeldpersonen)
|
||||||
|
{
|
||||||
|
<div class="collapsible-container">
|
||||||
|
<input type="button" class="toggle-btn2" value="@relatedPerson.FormattedName" />
|
||||||
|
<div style="display: none;" class="kollabierbar">
|
||||||
|
<table class="width-inheriting-table">
|
||||||
|
<tbody>
|
||||||
|
<tr class="testklasse">
|
||||||
|
<td class="customer-td">Rolle:</td>
|
||||||
|
<td class="contentTd">@relatedPerson.Rolle</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="testklasse">
|
||||||
|
<td class="customer-td">Adresse:</td>
|
||||||
|
<td class="contentTd">@relatedPerson.StrNameNr</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="testklasse">
|
||||||
|
<td class="customer-td"></td>
|
||||||
|
<td class="contentTd">@relatedPerson.PLZOrt</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="testklasse">
|
||||||
|
<td class="customer-td">Tel.:</td>
|
||||||
|
<td class="contentTd">
|
||||||
|
<a style="color: black" href="tel:@relatedPerson.TelNr">@relatedPerson.TelNr</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="testklasse">
|
||||||
|
<td class="customer-td">Mobil:</td>
|
||||||
|
<td class="contentTd">
|
||||||
|
<a style="color: black" href="tel:@relatedPerson.Mobil">@relatedPerson.Mobil</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="testklasse">
|
||||||
|
<td class="customer-td">E-Mail</td>
|
||||||
|
<td class="contentTd">
|
||||||
|
<a style="color: black" href="mailto:@relatedPerson.EMail">@relatedPerson.EMail</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="testklasse">
|
||||||
|
<td class="customer-td">Fax:</td>
|
||||||
|
<td class="contentTd">@relatedPerson.Fax</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@*<div class="input-wrapper" style="display: @Model.TabControlDisplayValue;">
|
||||||
<div class="customer-tab">
|
<div class="customer-tab">
|
||||||
<input type="button" class="customer-tab-link" id="customer-tab-1" onclick="focusOnCustomerTab(1)" value="Details"/>
|
<input type="button" class="customer-tab-link" id="customer-tab-1" onclick="focusOnCustomerTab(1)" value="Details"/>
|
||||||
<input type="button" class="customer-tab-link" id="customer-tab-2" onclick="focusOnCustomerTab(2)" value="Abwesenheiten"/>
|
<input type="button" class="customer-tab-link" id="customer-tab-2" onclick="focusOnCustomerTab(2)" value="Abwesenheiten"/>
|
||||||
@@ -302,7 +503,7 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>*@
|
||||||
<script>
|
<script>
|
||||||
$(".dropdownlist-for").css("height", '@AbstractModel.DropdownHeight' + "px");
|
$(".dropdownlist-for").css("height", '@AbstractModel.DropdownHeight' + "px");
|
||||||
</script>
|
</script>
|
||||||
@@ -4,6 +4,17 @@
|
|||||||
@model MainModel
|
@model MainModel
|
||||||
@{
|
@{
|
||||||
ViewBag.Title = "BeWoPlaner Mobil";
|
ViewBag.Title = "BeWoPlaner Mobil";
|
||||||
|
|
||||||
|
var loginState = TempData[MobileUtils.TempDataLoginStateKey] as BeWoLoginState;
|
||||||
|
|
||||||
|
if (loginState != null && loginState.Message != null)
|
||||||
|
{
|
||||||
|
var loginStateMessage = new HtmlString(loginState.Message);
|
||||||
|
|
||||||
|
<script>
|
||||||
|
toggleErrorPopup('@loginStateMessage', 3);
|
||||||
|
</script>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<div id="zeiterfassung">
|
<div id="zeiterfassung">
|
||||||
@@ -104,8 +115,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<div id="supportConceptListContainer">
|
<div id="supportConceptListContainer">
|
||||||
@foreach(var scListItem in Model.SupportConceptListObjects) {
|
@foreach (var scListItem in Model.SupportConceptListObjects)
|
||||||
using(Html.BeginForm("SelectSupportConcept", "Main", FormMethod.Post, new { id = "supportConceptForm_" + scListItem.CostBearer2SupportConceptOid }))
|
{
|
||||||
|
using (Html.BeginForm("SelectSupportConcept", "Main", FormMethod.Post, new { id = "supportConceptForm_" + scListItem.CostBearer2SupportConceptOid }))
|
||||||
{
|
{
|
||||||
<div class="supportConceptDiv" onclick="selectSupportConcept('@scListItem.CostBearer2SupportConceptOid')">
|
<div class="supportConceptDiv" onclick="selectSupportConcept('@scListItem.CostBearer2SupportConceptOid')">
|
||||||
<p class="listP">@scListItem.NameAndDateOfBirth</p>
|
<p class="listP">@scListItem.NameAndDateOfBirth</p>
|
||||||
@@ -390,7 +402,7 @@
|
|||||||
|
|
||||||
@(record.GroupOid != null ? string.Format("{0:###0.#} ({0:###0.#})", rd) : string.Format("{0:###0.#} ({1:###0.#})", (record.End.Value - record.Start.Value).TotalMinutes, rd))
|
@(record.GroupOid != null ? string.Format("{0:###0.#} ({0:###0.#})", rd) : string.Format("{0:###0.#} ({1:###0.#})", (record.End.Value - record.Start.Value).TotalMinutes, rd))
|
||||||
}
|
}
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@{
|
@{
|
||||||
@@ -558,9 +570,10 @@
|
|||||||
{
|
{
|
||||||
@Html.Raw("JA")
|
@Html.Raw("JA")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
</tr>}
|
</tr>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -731,7 +744,7 @@
|
|||||||
|
|
||||||
<input id="SaveRecordOID" readonly name="OID" style="display: none" />
|
<input id="SaveRecordOID" readonly name="OID" style="display: none" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="signature-buttons-container">
|
<div id="signature-buttons-container">
|
||||||
<input type="button" class="signature-button" onclick="loescheUnterschrift(canvas, ctx)" value="Neu" />
|
<input type="button" class="signature-button" onclick="loescheUnterschrift(canvas, ctx)" value="Neu" />
|
||||||
<input type="button" class="signature-button" onclick="speichereUnterschrift()" value="Speichern" />
|
<input type="button" class="signature-button" onclick="speichereUnterschrift()" value="Speichern" />
|
||||||
|
|||||||
@@ -91,7 +91,8 @@
|
|||||||
<div id="errorPopupDiv">
|
<div id="errorPopupDiv">
|
||||||
<h4 id="errorPopupTitle" class="error-text">Fehler</h4>
|
<h4 id="errorPopupTitle" class="error-text">Fehler</h4>
|
||||||
<p id="errorPopupText" class="center-aligned-text-element">Ein Fehler ist aufgetreten</p>
|
<p id="errorPopupText" class="center-aligned-text-element">Ein Fehler ist aufgetreten</p>
|
||||||
<div id="errorPopupBtnDiv" class="center-aligned-text-element">
|
<div id="errorPopupContentDiv" class="center-aligned-text-element"></div>
|
||||||
|
<div id="errorPopupBtnDiv" class="center-aligned-text-element" style="margin-top: 1em;">
|
||||||
<input id="errorPopupOkBtn" type="button" class="popupBtn" value="OK" onclick="toggleErrorPopup('')" />
|
<input id="errorPopupOkBtn" type="button" class="popupBtn" value="OK" onclick="toggleErrorPopup('')" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<configSections>
|
<configSections>
|
||||||
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
|
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
|
||||||
</configSections>
|
</configSections>
|
||||||
<system.diagnostics>
|
<system.diagnostics>
|
||||||
<sources>
|
<sources>
|
||||||
<source name="System.ServiceModel" switchValue="All">
|
<source name="System.ServiceModel" switchValue="All">
|
||||||
<listeners>
|
<listeners>
|
||||||
<add type="System.Diagnostics.DefaultTraceListener" name="Default">
|
<add type="System.Diagnostics.DefaultTraceListener" name="Default">
|
||||||
<filter type=""/>
|
<filter type="" />
|
||||||
</add>
|
</add>
|
||||||
<add initializeData="logs\Traces.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="traceListener" traceOutputOptions="DateTime">
|
<add initializeData="logs\Traces.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="traceListener" traceOutputOptions="DateTime">
|
||||||
<filter type=""/>
|
<filter type="" />
|
||||||
</add>
|
</add>
|
||||||
</listeners>
|
</listeners>
|
||||||
</source>
|
</source>
|
||||||
@@ -19,108 +19,106 @@
|
|||||||
</system.diagnostics>
|
</system.diagnostics>
|
||||||
<log4net debug="true">
|
<log4net debug="true">
|
||||||
<appender name="logFile" type="log4net.Appender.RollingFileAppender,log4net">
|
<appender name="logFile" type="log4net.Appender.RollingFileAppender,log4net">
|
||||||
<param name="File" value="logs\mobilelog.txt"/>
|
<param name="File" value="logs\mobilelog.txt" />
|
||||||
<param name="AppendToFile" value="true"/>
|
<param name="AppendToFile" value="true" />
|
||||||
<param name="RollingStyle" value="Date"/>
|
<param name="RollingStyle" value="Date" />
|
||||||
<param name="DatePattern" value="dd.MM.yyyy"/>
|
<param name="DatePattern" value="dd.MM.yyyy" />
|
||||||
<param name="StaticLogFileName" value="true"/>
|
<param name="StaticLogFileName" value="true" />
|
||||||
<layout type="log4net.Layout.PatternLayout,log4net">
|
<layout type="log4net.Layout.PatternLayout,log4net">
|
||||||
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
|
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
<root>
|
<root>
|
||||||
<priority value="INFO"/>
|
<priority value="INFO" />
|
||||||
<appender-ref ref="logFile"/>
|
<appender-ref ref="logFile" />
|
||||||
</root>
|
</root>
|
||||||
</log4net>
|
</log4net>
|
||||||
<system.webServer>
|
<system.webServer>
|
||||||
<validation validateIntegratedModeConfiguration="false"/>
|
<validation validateIntegratedModeConfiguration="false" />
|
||||||
<modules>
|
<modules>
|
||||||
<add name="ASPHibernateSession" type="BeWoPlanerMobil.Service.ASPHibernateSessionManager, BeWoPlanerMobil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
|
<add name="ASPHibernateSession" type="BeWoPlanerMobil.Service.ASPHibernateSessionManager, BeWoPlanerMobil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||||
</modules>
|
</modules>
|
||||||
<handlers>
|
<handlers>
|
||||||
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit"/>
|
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
|
||||||
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"/>
|
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
|
||||||
<remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
|
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
|
||||||
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0"/>
|
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
|
||||||
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0"/>
|
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
|
||||||
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
|
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
|
||||||
</handlers>
|
</handlers>
|
||||||
<directoryBrowse enabled="true"/>
|
<directoryBrowse enabled="true" />
|
||||||
</system.webServer>
|
</system.webServer>
|
||||||
<system.serviceModel>
|
<system.serviceModel>
|
||||||
<behaviors>
|
<behaviors>
|
||||||
<endpointBehaviors>
|
<endpointBehaviors>
|
||||||
<behavior name="SecurityBehavior">
|
<behavior name="SecurityBehavior">
|
||||||
<MultitenancyExtension/>
|
<MultitenancyExtension />
|
||||||
<SecurityExtension/>
|
<SecurityExtension />
|
||||||
</behavior>
|
</behavior>
|
||||||
<behavior name="SecurityAndSessionBehavior">
|
<behavior name="SecurityAndSessionBehavior">
|
||||||
<!--wichtig: erst Mulittenancy dann session dann security!-->
|
<!--wichtig: erst Mulittenancy dann session dann security!-->
|
||||||
<MultitenancyExtension/>
|
<MultitenancyExtension />
|
||||||
<HibernateSessionExtension/>
|
<HibernateSessionExtension />
|
||||||
<SecurityExtension/>
|
<SecurityExtension />
|
||||||
</behavior>
|
</behavior>
|
||||||
</endpointBehaviors>
|
</endpointBehaviors>
|
||||||
<serviceBehaviors>
|
<serviceBehaviors>
|
||||||
<behavior name="returnFaults">
|
<behavior name="returnFaults">
|
||||||
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
|
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
|
||||||
<serviceDebug includeExceptionDetailInFaults="true"/>
|
<serviceDebug includeExceptionDetailInFaults="true" />
|
||||||
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentSessions="1000"/>
|
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentSessions="1000" />
|
||||||
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
|
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
|
||||||
</behavior>
|
</behavior>
|
||||||
</serviceBehaviors>
|
</serviceBehaviors>
|
||||||
</behaviors>
|
</behaviors>
|
||||||
<extensions>
|
<extensions>
|
||||||
<behaviorExtensions>
|
<behaviorExtensions>
|
||||||
<add name="MultitenancyExtension" type="BeWo.Service.Multitenancy.MultitenancyBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
|
<add name="MultitenancyExtension" type="BeWo.Service.Multitenancy.MultitenancyBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||||
<add name="SecurityExtension" type="BeWo.Service.Security.SecurityBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
|
<add name="SecurityExtension" type="BeWo.Service.Security.SecurityBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||||
<add name="HibernateSessionExtension" type="BeWo.Service.UnitOfWork.HibernateSessionBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
|
<add name="HibernateSessionExtension" type="BeWo.Service.UnitOfWork.HibernateSessionBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||||
</behaviorExtensions>
|
</behaviorExtensions>
|
||||||
</extensions>
|
</extensions>
|
||||||
<bindings>
|
<bindings>
|
||||||
<basicHttpBinding>
|
<basicHttpBinding>
|
||||||
<binding name="BeWoBasicEndpoint" closeTimeout="00:05:00" openTimeout="00:05:00" receiveTimeout="00:10:00" sendTimeout="00:05:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
|
<binding name="BeWoBasicEndpoint" closeTimeout="00:05:00" openTimeout="00:05:00" receiveTimeout="00:10:00" sendTimeout="00:05:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
|
||||||
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
|
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
|
||||||
<security mode="None"/>
|
<security mode="None" />
|
||||||
</binding>
|
</binding>
|
||||||
<binding name="BeWoStreamingEndpoint" receiveTimeout="10:10:00" sendTimeout="10:01:00" maxBufferSize="65536" maxReceivedMessageSize="67108864" messageEncoding="Text" transferMode="StreamedRequest" useDefaultWebProxy="true">
|
<binding name="BeWoStreamingEndpoint" receiveTimeout="10:10:00" sendTimeout="10:01:00" maxBufferSize="65536" maxReceivedMessageSize="67108864" messageEncoding="Text" transferMode="StreamedRequest" useDefaultWebProxy="true">
|
||||||
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
|
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
|
||||||
<security mode="None"/>
|
<security mode="None" />
|
||||||
</binding>
|
</binding>
|
||||||
<binding name="QueryServiceEndpoint" closeTimeout="00:05:00" openTimeout="00:05:00" receiveTimeout="00:10:00" sendTimeout="00:05:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
|
<binding name="QueryServiceEndpoint" closeTimeout="00:05:00" openTimeout="00:05:00" receiveTimeout="00:10:00" sendTimeout="00:05:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
|
||||||
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
|
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
|
||||||
<security mode="None">
|
<security mode="None">
|
||||||
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
|
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
|
||||||
<message clientCredentialType="UserName" algorithmSuite="Default"/>
|
<message clientCredentialType="UserName" algorithmSuite="Default" />
|
||||||
</security>
|
</security>
|
||||||
</binding>
|
</binding>
|
||||||
</basicHttpBinding>
|
</basicHttpBinding>
|
||||||
</bindings>
|
</bindings>
|
||||||
<client>
|
<client>
|
||||||
<endpoint binding="basicHttpBinding" bindingConfiguration="QueryServiceEndpoint" contract="QueryService.IQueryService" name="QueryServiceEndpoint"/>
|
<endpoint binding="basicHttpBinding" bindingConfiguration="QueryServiceEndpoint" contract="QueryService.IQueryService" name="QueryServiceEndpoint" />
|
||||||
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoStreamingEndpoint" contract="BeWo.ServiceProxy.IStreamingService" name="StreamingServiceEndpoint"/>
|
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoStreamingEndpoint" contract="BeWo.ServiceProxy.IStreamingService" name="StreamingServiceEndpoint" />
|
||||||
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IEmployeeService" name="EmployeeServiceEndpoint"/>
|
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IEmployeeService" name="EmployeeServiceEndpoint" />
|
||||||
<endpoint behaviorConfiguration="BeWoServiceBehavior" binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.ICustomerService" name="CustomerServiceEndpoint"/>
|
<endpoint behaviorConfiguration="BeWoServiceBehavior" binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.ICustomerService" name="CustomerServiceEndpoint" />
|
||||||
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IUserService" name="UserServiceEndpoint"/>
|
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IUserService" name="UserServiceEndpoint" />
|
||||||
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IValueListService" name="ValueListServiceEndpoint"/>
|
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IValueListService" name="ValueListServiceEndpoint" />
|
||||||
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IDownloadService" name="DownloadServiceEndpoint"/>
|
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IDownloadService" name="DownloadServiceEndpoint" />
|
||||||
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IResourceService" name="BeWoBasicEndpoint"/>
|
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IResourceService" name="BeWoBasicEndpoint" />
|
||||||
<endpoint behaviorConfiguration="BeWoServiceBehavior" binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IOperationsService" name="OperationsServiceEndpoint"/>
|
<endpoint behaviorConfiguration="BeWoServiceBehavior" binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IOperationsService" name="OperationsServiceEndpoint" />
|
||||||
<endpoint behaviorConfiguration="BeWoServiceBehavior" binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IAccountingService" name="AccountingServiceEndpoint"/>
|
<endpoint behaviorConfiguration="BeWoServiceBehavior" binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IAccountingService" name="AccountingServiceEndpoint" />
|
||||||
<endpoint behaviorConfiguration="BeWoServiceBehavior" binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IAnalysisService" name="AnalysisServiceEndpoint"/>
|
<endpoint behaviorConfiguration="BeWoServiceBehavior" binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IAnalysisService" name="AnalysisServiceEndpoint" />
|
||||||
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IMailService" name="MailServiceEndpoint"/>
|
<endpoint binding="basicHttpBinding" bindingConfiguration="BeWoBasicEndpoint" contract="BeWo.ServiceProxy.IMailService" name="MailServiceEndpoint" />
|
||||||
</client>
|
</client>
|
||||||
</system.serviceModel>
|
</system.serviceModel>
|
||||||
<appSettings>
|
<appSettings>
|
||||||
<add key="webpages:Version" value="2.0.0.0"/>
|
<add key="webpages:Version" value="2.0.0.0" />
|
||||||
<add key="webpages:Enabled" value="false"/>
|
<add key="webpages:Enabled" value="false" />
|
||||||
<add key="PreserveLoginUrl" value="true"/>
|
<add key="PreserveLoginUrl" value="true" />
|
||||||
<add key="ClientValidationEnabled" value="true"/>
|
<add key="ClientValidationEnabled" value="true" />
|
||||||
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
|
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
|
||||||
<!--<add key="MultitenancyPath" value="C:\Users\Lyndon\Documents\beyondSoft\BeWo\Host\Multitenancy\"/>-->
|
<add key="MultitenancyPath" value="..\Host\Multitenancy\" />
|
||||||
<!--<add key="MultitenancyPath" value="D:\Projects\BeWo\Host\Multitenancy\"/>-->
|
|
||||||
<add key="MultitenancyPath" value="..\Host\Multitenancy\"/>
|
|
||||||
<add key="LicenseInfoUrl" value="https://support.bewoplaner.de/api/getlicensecount.php?k=[TENANT]" />
|
<add key="LicenseInfoUrl" value="https://support.bewoplaner.de/api/getlicensecount.php?k=[TENANT]" />
|
||||||
<add key="LicenseOrderUrl" value="https://support.bewoplaner.de/lizenzbestellung/?k=[TENANT]" />
|
<add key="LicenseOrderUrl" value="https://support.bewoplaner.de/lizenzbestellung/?k=[TENANT]" />
|
||||||
<add key="LicenseCancellationUrl" value="https://support.bewoplaner.de/api/licencecancellation.php?k=[TENANT]" />
|
<add key="LicenseCancellationUrl" value="https://support.bewoplaner.de/api/licencecancellation.php?k=[TENANT]" />
|
||||||
@@ -140,51 +138,51 @@
|
|||||||
</httpModules>-->
|
</httpModules>-->
|
||||||
<!-- ggf. wieder auskomentieren//ergebnis: auskommentieren weil lohnt nicht
|
<!-- ggf. wieder auskomentieren//ergebnis: auskommentieren weil lohnt nicht
|
||||||
<sessionState timeout="525600"/>-->
|
<sessionState timeout="525600"/>-->
|
||||||
<compilation debug="true" defaultLanguage="c#" targetFramework="4.5">
|
<compilation debug="true" defaultLanguage="c#" targetFramework="4.7.2">
|
||||||
<assemblies>
|
<assemblies>
|
||||||
<add assembly="BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
|
<add assembly="BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||||
</assemblies>
|
</assemblies>
|
||||||
</compilation>
|
</compilation>
|
||||||
<pages controlRenderingCompatibilityVersion="4.0">
|
<pages controlRenderingCompatibilityVersion="4.0">
|
||||||
<namespaces>
|
<namespaces>
|
||||||
<add namespace="System.Web.Helpers"/>
|
<add namespace="System.Web.Helpers" />
|
||||||
<add namespace="System.Web.Mvc"/>
|
<add namespace="System.Web.Mvc" />
|
||||||
<add namespace="System.Web.Mvc.Ajax"/>
|
<add namespace="System.Web.Mvc.Ajax" />
|
||||||
<add namespace="System.Web.Mvc.Html"/>
|
<add namespace="System.Web.Mvc.Html" />
|
||||||
<add namespace="System.Web.Optimization"/>
|
<add namespace="System.Web.Optimization" />
|
||||||
<add namespace="System.Web.Routing"/>
|
<add namespace="System.Web.Routing" />
|
||||||
<add namespace="System.Web.WebPages"/>
|
<add namespace="System.Web.WebPages" />
|
||||||
</namespaces>
|
</namespaces>
|
||||||
</pages>
|
</pages>
|
||||||
<authentication mode="Forms">
|
<authentication mode="Forms">
|
||||||
<forms loginUrl="~/Login"/>
|
<forms loginUrl="~/Login" />
|
||||||
</authentication>
|
</authentication>
|
||||||
</system.web>
|
</system.web>
|
||||||
<runtime>
|
<runtime>
|
||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
|
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
|
||||||
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
|
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
|
||||||
<bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
|
<bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
|
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
|
||||||
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35"/>
|
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0"/>
|
<bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
|
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" culture="neutral"/>
|
<assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-2.5.1.0" newVersion="2.5.1.0"/>
|
<bindingRedirect oldVersion="0.0.0.0-2.5.1.0" newVersion="2.5.1.0" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
|
|||||||
@@ -22,5 +22,6 @@
|
|||||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net40" />
|
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net40" />
|
||||||
<package id="Modernizr" version="2.6.2" targetFramework="net40" />
|
<package id="Modernizr" version="2.6.2" targetFramework="net40" />
|
||||||
<package id="Newtonsoft.Json" version="6.0.5" targetFramework="net40" requireReinstallation="true" />
|
<package id="Newtonsoft.Json" version="6.0.5" targetFramework="net40" requireReinstallation="true" />
|
||||||
|
<package id="RestSharp" version="106.10.1" targetFramework="net472" />
|
||||||
<package id="WebGrease" version="1.3.0" targetFramework="net40" />
|
<package id="WebGrease" version="1.3.0" targetFramework="net40" />
|
||||||
</packages>
|
</packages>
|
||||||
27
BeWoWebApi/App_Start/BundleConfig.cs
Normal file
27
BeWoWebApi/App_Start/BundleConfig.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Web;
|
||||||
|
using System.Web.Optimization;
|
||||||
|
|
||||||
|
namespace BeWoWebApi
|
||||||
|
{
|
||||||
|
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"));
|
||||||
|
|
||||||
|
bundles.Add(new StyleBundle("~/Content/css").Include(
|
||||||
|
"~/Content/bootstrap.css",
|
||||||
|
"~/Content/site.css"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
BeWoWebApi/App_Start/FilterConfig.cs
Normal file
13
BeWoWebApi/App_Start/FilterConfig.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Web;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
|
||||||
|
namespace BeWoWebApi
|
||||||
|
{
|
||||||
|
public class FilterConfig
|
||||||
|
{
|
||||||
|
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
|
||||||
|
{
|
||||||
|
filters.Add(new HandleErrorAttribute());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
BeWoWebApi/App_Start/RouteConfig.cs
Normal file
23
BeWoWebApi/App_Start/RouteConfig.cs
Normal file
@@ -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 BeWoWebApi
|
||||||
|
{
|
||||||
|
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 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
BeWoWebApi/App_Start/WebApiConfig.cs
Normal file
21
BeWoWebApi/App_Start/WebApiConfig.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Web.Http;
|
||||||
|
|
||||||
|
namespace BeWoWebApi
|
||||||
|
{
|
||||||
|
public static class WebApiConfig
|
||||||
|
{
|
||||||
|
public static void Register(HttpConfiguration config)
|
||||||
|
{
|
||||||
|
// Web API configuration and services
|
||||||
|
|
||||||
|
// Web API routes
|
||||||
|
config.MapHttpAttributeRoutes();
|
||||||
|
|
||||||
|
config.Routes.MapHttpRoute(
|
||||||
|
name: "DefaultApi",
|
||||||
|
routeTemplate: "api/{controller}/{id}",
|
||||||
|
defaults: new { id = RouteParameter.Optional }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
BeWoWebApi/Areas/HelpPage/ApiDescriptionExtensions.cs
Normal file
39
BeWoWebApi/Areas/HelpPage/ApiDescriptionExtensions.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Web;
|
||||||
|
using System.Web.Http.Description;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
113
BeWoWebApi/Areas/HelpPage/App_Start/HelpPageConfig.cs
Normal file
113
BeWoWebApi/Areas/HelpPage/App_Start/HelpPageConfig.cs
Normal file
@@ -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 BeWoWebApi.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 = "BeWoWebApi.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
|
||||||
|
}
|
||||||
|
}
|
||||||
63
BeWoWebApi/Areas/HelpPage/Controllers/HelpController.cs
Normal file
63
BeWoWebApi/Areas/HelpPage/Controllers/HelpController.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using System.Web.Http;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
using BeWoWebApi.Areas.HelpPage.ModelDescriptions;
|
||||||
|
using BeWoWebApi.Areas.HelpPage.Models;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
134
BeWoWebApi/Areas/HelpPage/HelpPage.css
Normal file
134
BeWoWebApi/Areas/HelpPage/HelpPage.css
Normal file
@@ -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;
|
||||||
|
}
|
||||||
26
BeWoWebApi/Areas/HelpPage/HelpPageAreaRegistration.cs
Normal file
26
BeWoWebApi/Areas/HelpPage/HelpPageAreaRegistration.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Web.Http;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
467
BeWoWebApi/Areas/HelpPage/HelpPageConfigurationExtensions.cs
Normal file
467
BeWoWebApi/Areas/HelpPage/HelpPageConfigurationExtensions.cs
Normal file
@@ -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 BeWoWebApi.Areas.HelpPage.ModelDescriptions;
|
||||||
|
using BeWoWebApi.Areas.HelpPage.Models;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.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 BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
public class CollectionModelDescription : ModelDescription
|
||||||
|
{
|
||||||
|
public ModelDescription ElementDescription { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.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 BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
public class DictionaryModelDescription : KeyValuePairModelDescription
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
public class EnumTypeModelDescription : ModelDescription
|
||||||
|
{
|
||||||
|
public EnumTypeModelDescription()
|
||||||
|
{
|
||||||
|
Values = new Collection<EnumValueDescription>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<EnumValueDescription> Values { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
public class EnumValueDescription
|
||||||
|
{
|
||||||
|
public string Documentation { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
public interface IModelDocumentationProvider
|
||||||
|
{
|
||||||
|
string GetDocumentation(MemberInfo member);
|
||||||
|
|
||||||
|
string GetDocumentation(Type type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
public class KeyValuePairModelDescription : ModelDescription
|
||||||
|
{
|
||||||
|
public ModelDescription KeyModelDescription { get; set; }
|
||||||
|
|
||||||
|
public ModelDescription ValueModelDescription { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Describes a type model.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ModelDescription
|
||||||
|
{
|
||||||
|
public string Documentation { get; set; }
|
||||||
|
|
||||||
|
public Type ModelType { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,451 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Web.Http;
|
||||||
|
using System.Web.Http.Description;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Generates model descriptions for given types.
|
||||||
|
/// </summary>
|
||||||
|
public class ModelDescriptionGenerator
|
||||||
|
{
|
||||||
|
// Modify this to support more data annotation attributes.
|
||||||
|
private readonly IDictionary<Type, Func<object, string>> AnnotationTextGenerator = new Dictionary<Type, Func<object, string>>
|
||||||
|
{
|
||||||
|
{ typeof(RequiredAttribute), a => "Required" },
|
||||||
|
{ typeof(RangeAttribute), a =>
|
||||||
|
{
|
||||||
|
RangeAttribute range = (RangeAttribute)a;
|
||||||
|
return String.Format(CultureInfo.CurrentCulture, "Range: inclusive between {0} and {1}", range.Minimum, range.Maximum);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ typeof(MaxLengthAttribute), a =>
|
||||||
|
{
|
||||||
|
MaxLengthAttribute maxLength = (MaxLengthAttribute)a;
|
||||||
|
return String.Format(CultureInfo.CurrentCulture, "Max length: {0}", maxLength.Length);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ typeof(MinLengthAttribute), a =>
|
||||||
|
{
|
||||||
|
MinLengthAttribute minLength = (MinLengthAttribute)a;
|
||||||
|
return String.Format(CultureInfo.CurrentCulture, "Min length: {0}", minLength.Length);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ typeof(StringLengthAttribute), a =>
|
||||||
|
{
|
||||||
|
StringLengthAttribute strLength = (StringLengthAttribute)a;
|
||||||
|
return String.Format(CultureInfo.CurrentCulture, "String length: inclusive between {0} and {1}", strLength.MinimumLength, strLength.MaximumLength);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ typeof(DataTypeAttribute), a =>
|
||||||
|
{
|
||||||
|
DataTypeAttribute dataType = (DataTypeAttribute)a;
|
||||||
|
return String.Format(CultureInfo.CurrentCulture, "Data type: {0}", dataType.CustomDataType ?? dataType.DataType.ToString());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ typeof(RegularExpressionAttribute), a =>
|
||||||
|
{
|
||||||
|
RegularExpressionAttribute regularExpression = (RegularExpressionAttribute)a;
|
||||||
|
return String.Format(CultureInfo.CurrentCulture, "Matching regular expression pattern: {0}", regularExpression.Pattern);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modify this to add more default documentations.
|
||||||
|
private readonly IDictionary<Type, string> DefaultTypeDocumentation = new Dictionary<Type, string>
|
||||||
|
{
|
||||||
|
{ typeof(Int16), "integer" },
|
||||||
|
{ typeof(Int32), "integer" },
|
||||||
|
{ typeof(Int64), "integer" },
|
||||||
|
{ typeof(UInt16), "unsigned integer" },
|
||||||
|
{ typeof(UInt32), "unsigned integer" },
|
||||||
|
{ typeof(UInt64), "unsigned integer" },
|
||||||
|
{ typeof(Byte), "byte" },
|
||||||
|
{ typeof(Char), "character" },
|
||||||
|
{ typeof(SByte), "signed byte" },
|
||||||
|
{ typeof(Uri), "URI" },
|
||||||
|
{ typeof(Single), "decimal number" },
|
||||||
|
{ typeof(Double), "decimal number" },
|
||||||
|
{ typeof(Decimal), "decimal number" },
|
||||||
|
{ typeof(String), "string" },
|
||||||
|
{ typeof(Guid), "globally unique identifier" },
|
||||||
|
{ typeof(TimeSpan), "time interval" },
|
||||||
|
{ typeof(DateTime), "date" },
|
||||||
|
{ typeof(DateTimeOffset), "date" },
|
||||||
|
{ typeof(Boolean), "boolean" },
|
||||||
|
};
|
||||||
|
|
||||||
|
private Lazy<IModelDocumentationProvider> _documentationProvider;
|
||||||
|
|
||||||
|
public ModelDescriptionGenerator(HttpConfiguration config)
|
||||||
|
{
|
||||||
|
if (config == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("config");
|
||||||
|
}
|
||||||
|
|
||||||
|
_documentationProvider = new Lazy<IModelDocumentationProvider>(() => config.Services.GetDocumentationProvider() as IModelDocumentationProvider);
|
||||||
|
GeneratedModels = new Dictionary<string, ModelDescription>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, ModelDescription> GeneratedModels { get; private set; }
|
||||||
|
|
||||||
|
private IModelDocumentationProvider DocumentationProvider
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _documentationProvider.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelDescription GetOrCreateModelDescription(Type modelType)
|
||||||
|
{
|
||||||
|
if (modelType == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("modelType");
|
||||||
|
}
|
||||||
|
|
||||||
|
Type underlyingType = Nullable.GetUnderlyingType(modelType);
|
||||||
|
if (underlyingType != null)
|
||||||
|
{
|
||||||
|
modelType = underlyingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelDescription modelDescription;
|
||||||
|
string modelName = ModelNameHelper.GetModelName(modelType);
|
||||||
|
if (GeneratedModels.TryGetValue(modelName, out modelDescription))
|
||||||
|
{
|
||||||
|
if (modelType != modelDescription.ModelType)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
String.Format(
|
||||||
|
CultureInfo.CurrentCulture,
|
||||||
|
"A model description could not be created. Duplicate model name '{0}' was found for types '{1}' and '{2}'. " +
|
||||||
|
"Use the [ModelName] attribute to change the model name for at least one of the types so that it has a unique name.",
|
||||||
|
modelName,
|
||||||
|
modelDescription.ModelType.FullName,
|
||||||
|
modelType.FullName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return modelDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DefaultTypeDocumentation.ContainsKey(modelType))
|
||||||
|
{
|
||||||
|
return GenerateSimpleTypeModelDescription(modelType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelType.IsEnum)
|
||||||
|
{
|
||||||
|
return GenerateEnumTypeModelDescription(modelType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelType.IsGenericType)
|
||||||
|
{
|
||||||
|
Type[] genericArguments = modelType.GetGenericArguments();
|
||||||
|
|
||||||
|
if (genericArguments.Length == 1)
|
||||||
|
{
|
||||||
|
Type enumerableType = typeof(IEnumerable<>).MakeGenericType(genericArguments);
|
||||||
|
if (enumerableType.IsAssignableFrom(modelType))
|
||||||
|
{
|
||||||
|
return GenerateCollectionModelDescription(modelType, genericArguments[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (genericArguments.Length == 2)
|
||||||
|
{
|
||||||
|
Type dictionaryType = typeof(IDictionary<,>).MakeGenericType(genericArguments);
|
||||||
|
if (dictionaryType.IsAssignableFrom(modelType))
|
||||||
|
{
|
||||||
|
return GenerateDictionaryModelDescription(modelType, genericArguments[0], genericArguments[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type keyValuePairType = typeof(KeyValuePair<,>).MakeGenericType(genericArguments);
|
||||||
|
if (keyValuePairType.IsAssignableFrom(modelType))
|
||||||
|
{
|
||||||
|
return GenerateKeyValuePairModelDescription(modelType, genericArguments[0], genericArguments[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelType.IsArray)
|
||||||
|
{
|
||||||
|
Type elementType = modelType.GetElementType();
|
||||||
|
return GenerateCollectionModelDescription(modelType, elementType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelType == typeof(NameValueCollection))
|
||||||
|
{
|
||||||
|
return GenerateDictionaryModelDescription(modelType, typeof(string), typeof(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(IDictionary).IsAssignableFrom(modelType))
|
||||||
|
{
|
||||||
|
return GenerateDictionaryModelDescription(modelType, typeof(object), typeof(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(IEnumerable).IsAssignableFrom(modelType))
|
||||||
|
{
|
||||||
|
return GenerateCollectionModelDescription(modelType, typeof(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
return GenerateComplexTypeModelDescription(modelType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change this to provide different name for the member.
|
||||||
|
private static string GetMemberName(MemberInfo member, bool hasDataContractAttribute)
|
||||||
|
{
|
||||||
|
JsonPropertyAttribute jsonProperty = member.GetCustomAttribute<JsonPropertyAttribute>();
|
||||||
|
if (jsonProperty != null && !String.IsNullOrEmpty(jsonProperty.PropertyName))
|
||||||
|
{
|
||||||
|
return jsonProperty.PropertyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasDataContractAttribute)
|
||||||
|
{
|
||||||
|
DataMemberAttribute dataMember = member.GetCustomAttribute<DataMemberAttribute>();
|
||||||
|
if (dataMember != null && !String.IsNullOrEmpty(dataMember.Name))
|
||||||
|
{
|
||||||
|
return dataMember.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return member.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ShouldDisplayMember(MemberInfo member, bool hasDataContractAttribute)
|
||||||
|
{
|
||||||
|
JsonIgnoreAttribute jsonIgnore = member.GetCustomAttribute<JsonIgnoreAttribute>();
|
||||||
|
XmlIgnoreAttribute xmlIgnore = member.GetCustomAttribute<XmlIgnoreAttribute>();
|
||||||
|
IgnoreDataMemberAttribute ignoreDataMember = member.GetCustomAttribute<IgnoreDataMemberAttribute>();
|
||||||
|
NonSerializedAttribute nonSerialized = member.GetCustomAttribute<NonSerializedAttribute>();
|
||||||
|
ApiExplorerSettingsAttribute apiExplorerSetting = member.GetCustomAttribute<ApiExplorerSettingsAttribute>();
|
||||||
|
|
||||||
|
bool hasMemberAttribute = member.DeclaringType.IsEnum ?
|
||||||
|
member.GetCustomAttribute<EnumMemberAttribute>() != null :
|
||||||
|
member.GetCustomAttribute<DataMemberAttribute>() != null;
|
||||||
|
|
||||||
|
// Display member only if all the followings are true:
|
||||||
|
// no JsonIgnoreAttribute
|
||||||
|
// no XmlIgnoreAttribute
|
||||||
|
// no IgnoreDataMemberAttribute
|
||||||
|
// no NonSerializedAttribute
|
||||||
|
// no ApiExplorerSettingsAttribute with IgnoreApi set to true
|
||||||
|
// no DataContractAttribute without DataMemberAttribute or EnumMemberAttribute
|
||||||
|
return jsonIgnore == null &&
|
||||||
|
xmlIgnore == null &&
|
||||||
|
ignoreDataMember == null &&
|
||||||
|
nonSerialized == null &&
|
||||||
|
(apiExplorerSetting == null || !apiExplorerSetting.IgnoreApi) &&
|
||||||
|
(!hasDataContractAttribute || hasMemberAttribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string CreateDefaultDocumentation(Type type)
|
||||||
|
{
|
||||||
|
string documentation;
|
||||||
|
if (DefaultTypeDocumentation.TryGetValue(type, out documentation))
|
||||||
|
{
|
||||||
|
return documentation;
|
||||||
|
}
|
||||||
|
if (DocumentationProvider != null)
|
||||||
|
{
|
||||||
|
documentation = DocumentationProvider.GetDocumentation(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return documentation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateAnnotations(MemberInfo property, ParameterDescription propertyModel)
|
||||||
|
{
|
||||||
|
List<ParameterAnnotation> annotations = new List<ParameterAnnotation>();
|
||||||
|
|
||||||
|
IEnumerable<Attribute> attributes = property.GetCustomAttributes();
|
||||||
|
foreach (Attribute attribute in attributes)
|
||||||
|
{
|
||||||
|
Func<object, string> textGenerator;
|
||||||
|
if (AnnotationTextGenerator.TryGetValue(attribute.GetType(), out textGenerator))
|
||||||
|
{
|
||||||
|
annotations.Add(
|
||||||
|
new ParameterAnnotation
|
||||||
|
{
|
||||||
|
AnnotationAttribute = attribute,
|
||||||
|
Documentation = textGenerator(attribute)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rearrange the annotations
|
||||||
|
annotations.Sort((x, y) =>
|
||||||
|
{
|
||||||
|
// Special-case RequiredAttribute so that it shows up on top
|
||||||
|
if (x.AnnotationAttribute is RequiredAttribute)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (y.AnnotationAttribute is RequiredAttribute)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the rest based on alphabetic order of the documentation
|
||||||
|
return String.Compare(x.Documentation, y.Documentation, StringComparison.OrdinalIgnoreCase);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (ParameterAnnotation annotation in annotations)
|
||||||
|
{
|
||||||
|
propertyModel.Annotations.Add(annotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CollectionModelDescription GenerateCollectionModelDescription(Type modelType, Type elementType)
|
||||||
|
{
|
||||||
|
ModelDescription collectionModelDescription = GetOrCreateModelDescription(elementType);
|
||||||
|
if (collectionModelDescription != null)
|
||||||
|
{
|
||||||
|
return new CollectionModelDescription
|
||||||
|
{
|
||||||
|
Name = ModelNameHelper.GetModelName(modelType),
|
||||||
|
ModelType = modelType,
|
||||||
|
ElementDescription = collectionModelDescription
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelDescription GenerateComplexTypeModelDescription(Type modelType)
|
||||||
|
{
|
||||||
|
ComplexTypeModelDescription complexModelDescription = new ComplexTypeModelDescription
|
||||||
|
{
|
||||||
|
Name = ModelNameHelper.GetModelName(modelType),
|
||||||
|
ModelType = modelType,
|
||||||
|
Documentation = CreateDefaultDocumentation(modelType)
|
||||||
|
};
|
||||||
|
|
||||||
|
GeneratedModels.Add(complexModelDescription.Name, complexModelDescription);
|
||||||
|
bool hasDataContractAttribute = modelType.GetCustomAttribute<DataContractAttribute>() != null;
|
||||||
|
PropertyInfo[] properties = modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
foreach (PropertyInfo property in properties)
|
||||||
|
{
|
||||||
|
if (ShouldDisplayMember(property, hasDataContractAttribute))
|
||||||
|
{
|
||||||
|
ParameterDescription propertyModel = new ParameterDescription
|
||||||
|
{
|
||||||
|
Name = GetMemberName(property, hasDataContractAttribute)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (DocumentationProvider != null)
|
||||||
|
{
|
||||||
|
propertyModel.Documentation = DocumentationProvider.GetDocumentation(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateAnnotations(property, propertyModel);
|
||||||
|
complexModelDescription.Properties.Add(propertyModel);
|
||||||
|
propertyModel.TypeDescription = GetOrCreateModelDescription(property.PropertyType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldInfo[] fields = modelType.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
foreach (FieldInfo field in fields)
|
||||||
|
{
|
||||||
|
if (ShouldDisplayMember(field, hasDataContractAttribute))
|
||||||
|
{
|
||||||
|
ParameterDescription propertyModel = new ParameterDescription
|
||||||
|
{
|
||||||
|
Name = GetMemberName(field, hasDataContractAttribute)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (DocumentationProvider != null)
|
||||||
|
{
|
||||||
|
propertyModel.Documentation = DocumentationProvider.GetDocumentation(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
complexModelDescription.Properties.Add(propertyModel);
|
||||||
|
propertyModel.TypeDescription = GetOrCreateModelDescription(field.FieldType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return complexModelDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DictionaryModelDescription GenerateDictionaryModelDescription(Type modelType, Type keyType, Type valueType)
|
||||||
|
{
|
||||||
|
ModelDescription keyModelDescription = GetOrCreateModelDescription(keyType);
|
||||||
|
ModelDescription valueModelDescription = GetOrCreateModelDescription(valueType);
|
||||||
|
|
||||||
|
return new DictionaryModelDescription
|
||||||
|
{
|
||||||
|
Name = ModelNameHelper.GetModelName(modelType),
|
||||||
|
ModelType = modelType,
|
||||||
|
KeyModelDescription = keyModelDescription,
|
||||||
|
ValueModelDescription = valueModelDescription
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private EnumTypeModelDescription GenerateEnumTypeModelDescription(Type modelType)
|
||||||
|
{
|
||||||
|
EnumTypeModelDescription enumDescription = new EnumTypeModelDescription
|
||||||
|
{
|
||||||
|
Name = ModelNameHelper.GetModelName(modelType),
|
||||||
|
ModelType = modelType,
|
||||||
|
Documentation = CreateDefaultDocumentation(modelType)
|
||||||
|
};
|
||||||
|
bool hasDataContractAttribute = modelType.GetCustomAttribute<DataContractAttribute>() != null;
|
||||||
|
foreach (FieldInfo field in modelType.GetFields(BindingFlags.Public | BindingFlags.Static))
|
||||||
|
{
|
||||||
|
if (ShouldDisplayMember(field, hasDataContractAttribute))
|
||||||
|
{
|
||||||
|
EnumValueDescription enumValue = new EnumValueDescription
|
||||||
|
{
|
||||||
|
Name = field.Name,
|
||||||
|
Value = field.GetRawConstantValue().ToString()
|
||||||
|
};
|
||||||
|
if (DocumentationProvider != null)
|
||||||
|
{
|
||||||
|
enumValue.Documentation = DocumentationProvider.GetDocumentation(field);
|
||||||
|
}
|
||||||
|
enumDescription.Values.Add(enumValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GeneratedModels.Add(enumDescription.Name, enumDescription);
|
||||||
|
|
||||||
|
return enumDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
private KeyValuePairModelDescription GenerateKeyValuePairModelDescription(Type modelType, Type keyType, Type valueType)
|
||||||
|
{
|
||||||
|
ModelDescription keyModelDescription = GetOrCreateModelDescription(keyType);
|
||||||
|
ModelDescription valueModelDescription = GetOrCreateModelDescription(valueType);
|
||||||
|
|
||||||
|
return new KeyValuePairModelDescription
|
||||||
|
{
|
||||||
|
Name = ModelNameHelper.GetModelName(modelType),
|
||||||
|
ModelType = modelType,
|
||||||
|
KeyModelDescription = keyModelDescription,
|
||||||
|
ValueModelDescription = valueModelDescription
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelDescription GenerateSimpleTypeModelDescription(Type modelType)
|
||||||
|
{
|
||||||
|
SimpleTypeModelDescription simpleModelDescription = new SimpleTypeModelDescription
|
||||||
|
{
|
||||||
|
Name = ModelNameHelper.GetModelName(modelType),
|
||||||
|
ModelType = modelType,
|
||||||
|
Documentation = CreateDefaultDocumentation(modelType)
|
||||||
|
};
|
||||||
|
GeneratedModels.Add(simpleModelDescription.Name, simpleModelDescription);
|
||||||
|
|
||||||
|
return simpleModelDescription;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Use this attribute to change the name of the <see cref="ModelDescription"/> generated for a type.
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = false, Inherited = false)]
|
||||||
|
public sealed class ModelNameAttribute : Attribute
|
||||||
|
{
|
||||||
|
public ModelNameAttribute(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
internal static class ModelNameHelper
|
||||||
|
{
|
||||||
|
// Modify this to provide custom model name mapping.
|
||||||
|
public static string GetModelName(Type type)
|
||||||
|
{
|
||||||
|
ModelNameAttribute modelNameAttribute = type.GetCustomAttribute<ModelNameAttribute>();
|
||||||
|
if (modelNameAttribute != null && !String.IsNullOrEmpty(modelNameAttribute.Name))
|
||||||
|
{
|
||||||
|
return modelNameAttribute.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
string modelName = type.Name;
|
||||||
|
if (type.IsGenericType)
|
||||||
|
{
|
||||||
|
// Format the generic type name to something like: GenericOfAgurment1AndArgument2
|
||||||
|
Type genericType = type.GetGenericTypeDefinition();
|
||||||
|
Type[] genericArguments = type.GetGenericArguments();
|
||||||
|
string genericTypeName = genericType.Name;
|
||||||
|
|
||||||
|
// Trim the generic parameter counts from the name
|
||||||
|
genericTypeName = genericTypeName.Substring(0, genericTypeName.IndexOf('`'));
|
||||||
|
string[] argumentTypeNames = genericArguments.Select(t => GetModelName(t)).ToArray();
|
||||||
|
modelName = String.Format(CultureInfo.InvariantCulture, "{0}Of{1}", genericTypeName, String.Join("And", argumentTypeNames));
|
||||||
|
}
|
||||||
|
|
||||||
|
return modelName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
public class ParameterAnnotation
|
||||||
|
{
|
||||||
|
public Attribute AnnotationAttribute { get; set; }
|
||||||
|
|
||||||
|
public string Documentation { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
public class ParameterDescription
|
||||||
|
{
|
||||||
|
public ParameterDescription()
|
||||||
|
{
|
||||||
|
Annotations = new Collection<ParameterAnnotation>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ParameterAnnotation> Annotations { get; private set; }
|
||||||
|
|
||||||
|
public string Documentation { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public ModelDescription TypeDescription { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
{
|
||||||
|
public class SimpleTypeModelDescription : ModelDescription
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
108
BeWoWebApi/Areas/HelpPage/Models/HelpPageApiModel.cs
Normal file
108
BeWoWebApi/Areas/HelpPage/Models/HelpPageApiModel.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Web.Http.Description;
|
||||||
|
using BeWoWebApi.Areas.HelpPage.ModelDescriptions;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The model that represents an API displayed on the help page.
|
||||||
|
/// </summary>
|
||||||
|
public class HelpPageApiModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="HelpPageApiModel"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public HelpPageApiModel()
|
||||||
|
{
|
||||||
|
UriParameters = new Collection<ParameterDescription>();
|
||||||
|
SampleRequests = new Dictionary<MediaTypeHeaderValue, object>();
|
||||||
|
SampleResponses = new Dictionary<MediaTypeHeaderValue, object>();
|
||||||
|
ErrorMessages = new Collection<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="ApiDescription"/> that describes the API.
|
||||||
|
/// </summary>
|
||||||
|
public ApiDescription ApiDescription { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="ParameterDescription"/> collection that describes the URI parameters for the API.
|
||||||
|
/// </summary>
|
||||||
|
public Collection<ParameterDescription> UriParameters { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the documentation for the request.
|
||||||
|
/// </summary>
|
||||||
|
public string RequestDocumentation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="ModelDescription"/> that describes the request body.
|
||||||
|
/// </summary>
|
||||||
|
public ModelDescription RequestModelDescription { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the request body parameter descriptions.
|
||||||
|
/// </summary>
|
||||||
|
public IList<ParameterDescription> RequestBodyParameters
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetParameterDescriptions(RequestModelDescription);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="ModelDescription"/> that describes the resource.
|
||||||
|
/// </summary>
|
||||||
|
public ModelDescription ResourceDescription { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the resource property descriptions.
|
||||||
|
/// </summary>
|
||||||
|
public IList<ParameterDescription> ResourceProperties
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetParameterDescriptions(ResourceDescription);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sample requests associated with the API.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<MediaTypeHeaderValue, object> SampleRequests { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sample responses associated with the API.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<MediaTypeHeaderValue, object> SampleResponses { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the error messages associated with this model.
|
||||||
|
/// </summary>
|
||||||
|
public Collection<string> ErrorMessages { get; private set; }
|
||||||
|
|
||||||
|
private static IList<ParameterDescription> GetParameterDescriptions(ModelDescription modelDescription)
|
||||||
|
{
|
||||||
|
ComplexTypeModelDescription complexTypeModelDescription = modelDescription as ComplexTypeModelDescription;
|
||||||
|
if (complexTypeModelDescription != null)
|
||||||
|
{
|
||||||
|
return complexTypeModelDescription.Properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectionModelDescription collectionModelDescription = modelDescription as CollectionModelDescription;
|
||||||
|
if (collectionModelDescription != null)
|
||||||
|
{
|
||||||
|
complexTypeModelDescription = collectionModelDescription.ElementDescription as ComplexTypeModelDescription;
|
||||||
|
if (complexTypeModelDescription != null)
|
||||||
|
{
|
||||||
|
return complexTypeModelDescription.Properties;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,444 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Formatting;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Web.Http.Description;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class will generate the samples for the help page.
|
||||||
|
/// </summary>
|
||||||
|
public class HelpPageSampleGenerator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="HelpPageSampleGenerator"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public HelpPageSampleGenerator()
|
||||||
|
{
|
||||||
|
ActualHttpMessageTypes = new Dictionary<HelpPageSampleKey, Type>();
|
||||||
|
ActionSamples = new Dictionary<HelpPageSampleKey, object>();
|
||||||
|
SampleObjects = new Dictionary<Type, object>();
|
||||||
|
SampleObjectFactories = new List<Func<HelpPageSampleGenerator, Type, object>>
|
||||||
|
{
|
||||||
|
DefaultSampleObjectFactory,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets CLR types that are used as the content of <see cref="HttpRequestMessage"/> or <see cref="HttpResponseMessage"/>.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<HelpPageSampleKey, Type> ActualHttpMessageTypes { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the objects that are used directly as samples for certain actions.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<HelpPageSampleKey, object> ActionSamples { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the objects that are serialized as samples by the supported formatters.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<Type, object> SampleObjects { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets factories for the objects that the supported formatters will serialize as samples. Processed in order,
|
||||||
|
/// stopping when the factory successfully returns a non-<see langref="null"/> object.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Collection includes just <see cref="ObjectGenerator.GenerateObject(Type)"/> initially. Use
|
||||||
|
/// <code>SampleObjectFactories.Insert(0, func)</code> to provide an override and
|
||||||
|
/// <code>SampleObjectFactories.Add(func)</code> to provide a fallback.</remarks>
|
||||||
|
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
|
||||||
|
Justification = "This is an appropriate nesting of generic types")]
|
||||||
|
public IList<Func<HelpPageSampleGenerator, Type, object>> SampleObjectFactories { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the request body samples for a given <see cref="ApiDescription"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="api">The <see cref="ApiDescription"/>.</param>
|
||||||
|
/// <returns>The samples keyed by media type.</returns>
|
||||||
|
public IDictionary<MediaTypeHeaderValue, object> GetSampleRequests(ApiDescription api)
|
||||||
|
{
|
||||||
|
return GetSample(api, SampleDirection.Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the response body samples for a given <see cref="ApiDescription"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="api">The <see cref="ApiDescription"/>.</param>
|
||||||
|
/// <returns>The samples keyed by media type.</returns>
|
||||||
|
public IDictionary<MediaTypeHeaderValue, object> GetSampleResponses(ApiDescription api)
|
||||||
|
{
|
||||||
|
return GetSample(api, SampleDirection.Response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the request or response body samples.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="api">The <see cref="ApiDescription"/>.</param>
|
||||||
|
/// <param name="sampleDirection">The value indicating whether the sample is for a request or for a response.</param>
|
||||||
|
/// <returns>The samples keyed by media type.</returns>
|
||||||
|
public virtual IDictionary<MediaTypeHeaderValue, object> GetSample(ApiDescription api, SampleDirection sampleDirection)
|
||||||
|
{
|
||||||
|
if (api == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("api");
|
||||||
|
}
|
||||||
|
string controllerName = api.ActionDescriptor.ControllerDescriptor.ControllerName;
|
||||||
|
string actionName = api.ActionDescriptor.ActionName;
|
||||||
|
IEnumerable<string> parameterNames = api.ParameterDescriptions.Select(p => p.Name);
|
||||||
|
Collection<MediaTypeFormatter> formatters;
|
||||||
|
Type type = ResolveType(api, controllerName, actionName, parameterNames, sampleDirection, out formatters);
|
||||||
|
var samples = new Dictionary<MediaTypeHeaderValue, object>();
|
||||||
|
|
||||||
|
// Use the samples provided directly for actions
|
||||||
|
var actionSamples = GetAllActionSamples(controllerName, actionName, parameterNames, sampleDirection);
|
||||||
|
foreach (var actionSample in actionSamples)
|
||||||
|
{
|
||||||
|
samples.Add(actionSample.Key.MediaType, WrapSampleIfString(actionSample.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the sample generation based on formatters only if an action doesn't return an HttpResponseMessage.
|
||||||
|
// Here we cannot rely on formatters because we don't know what's in the HttpResponseMessage, it might not even use formatters.
|
||||||
|
if (type != null && !typeof(HttpResponseMessage).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
object sampleObject = GetSampleObject(type);
|
||||||
|
foreach (var formatter in formatters)
|
||||||
|
{
|
||||||
|
foreach (MediaTypeHeaderValue mediaType in formatter.SupportedMediaTypes)
|
||||||
|
{
|
||||||
|
if (!samples.ContainsKey(mediaType))
|
||||||
|
{
|
||||||
|
object sample = GetActionSample(controllerName, actionName, parameterNames, type, formatter, mediaType, sampleDirection);
|
||||||
|
|
||||||
|
// If no sample found, try generate sample using formatter and sample object
|
||||||
|
if (sample == null && sampleObject != null)
|
||||||
|
{
|
||||||
|
sample = WriteSampleObjectUsingFormatter(formatter, sampleObject, type, mediaType);
|
||||||
|
}
|
||||||
|
|
||||||
|
samples.Add(mediaType, WrapSampleIfString(sample));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Search for samples that are provided directly through <see cref="ActionSamples"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="controllerName">Name of the controller.</param>
|
||||||
|
/// <param name="actionName">Name of the action.</param>
|
||||||
|
/// <param name="parameterNames">The parameter names.</param>
|
||||||
|
/// <param name="type">The CLR type.</param>
|
||||||
|
/// <param name="formatter">The formatter.</param>
|
||||||
|
/// <param name="mediaType">The media type.</param>
|
||||||
|
/// <param name="sampleDirection">The value indicating whether the sample is for a request or for a response.</param>
|
||||||
|
/// <returns>The sample that matches the parameters.</returns>
|
||||||
|
public virtual object GetActionSample(string controllerName, string actionName, IEnumerable<string> parameterNames, Type type, MediaTypeFormatter formatter, MediaTypeHeaderValue mediaType, SampleDirection sampleDirection)
|
||||||
|
{
|
||||||
|
object sample;
|
||||||
|
|
||||||
|
// First, try to get the sample provided for the specified mediaType, sampleDirection, controllerName, actionName and parameterNames.
|
||||||
|
// If not found, try to get the sample provided for the specified mediaType, sampleDirection, controllerName and actionName regardless of the parameterNames.
|
||||||
|
// If still not found, try to get the sample provided for the specified mediaType and type.
|
||||||
|
// Finally, try to get the sample provided for the specified mediaType.
|
||||||
|
if (ActionSamples.TryGetValue(new HelpPageSampleKey(mediaType, sampleDirection, controllerName, actionName, parameterNames), out sample) ||
|
||||||
|
ActionSamples.TryGetValue(new HelpPageSampleKey(mediaType, sampleDirection, controllerName, actionName, new[] { "*" }), out sample) ||
|
||||||
|
ActionSamples.TryGetValue(new HelpPageSampleKey(mediaType, type), out sample) ||
|
||||||
|
ActionSamples.TryGetValue(new HelpPageSampleKey(mediaType), out sample))
|
||||||
|
{
|
||||||
|
return sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sample object that will be serialized by the formatters.
|
||||||
|
/// First, it will look at the <see cref="SampleObjects"/>. If no sample object is found, it will try to create
|
||||||
|
/// one using <see cref="DefaultSampleObjectFactory"/> (which wraps an <see cref="ObjectGenerator"/>) and other
|
||||||
|
/// factories in <see cref="SampleObjectFactories"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type.</param>
|
||||||
|
/// <returns>The sample object.</returns>
|
||||||
|
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
|
||||||
|
Justification = "Even if all items in SampleObjectFactories throw, problem will be visible as missing sample.")]
|
||||||
|
public virtual object GetSampleObject(Type type)
|
||||||
|
{
|
||||||
|
object sampleObject;
|
||||||
|
|
||||||
|
if (!SampleObjects.TryGetValue(type, out sampleObject))
|
||||||
|
{
|
||||||
|
// No specific object available, try our factories.
|
||||||
|
foreach (Func<HelpPageSampleGenerator, Type, object> factory in SampleObjectFactories)
|
||||||
|
{
|
||||||
|
if (factory == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sampleObject = factory(this, type);
|
||||||
|
if (sampleObject != null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore any problems encountered in the factory; go on to the next one (if any).
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sampleObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resolves the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> passed to the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="api">The <see cref="ApiDescription"/>.</param>
|
||||||
|
/// <returns>The type.</returns>
|
||||||
|
public virtual Type ResolveHttpRequestMessageType(ApiDescription api)
|
||||||
|
{
|
||||||
|
string controllerName = api.ActionDescriptor.ControllerDescriptor.ControllerName;
|
||||||
|
string actionName = api.ActionDescriptor.ActionName;
|
||||||
|
IEnumerable<string> parameterNames = api.ParameterDescriptions.Select(p => p.Name);
|
||||||
|
Collection<MediaTypeFormatter> formatters;
|
||||||
|
return ResolveType(api, controllerName, actionName, parameterNames, SampleDirection.Request, out formatters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resolves the type of the action parameter or return value when <see cref="HttpRequestMessage"/> or <see cref="HttpResponseMessage"/> is used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="api">The <see cref="ApiDescription"/>.</param>
|
||||||
|
/// <param name="controllerName">Name of the controller.</param>
|
||||||
|
/// <param name="actionName">Name of the action.</param>
|
||||||
|
/// <param name="parameterNames">The parameter names.</param>
|
||||||
|
/// <param name="sampleDirection">The value indicating whether the sample is for a request or a response.</param>
|
||||||
|
/// <param name="formatters">The formatters.</param>
|
||||||
|
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", Justification = "This is only used in advanced scenarios.")]
|
||||||
|
public virtual Type ResolveType(ApiDescription api, string controllerName, string actionName, IEnumerable<string> parameterNames, SampleDirection sampleDirection, out Collection<MediaTypeFormatter> formatters)
|
||||||
|
{
|
||||||
|
if (!Enum.IsDefined(typeof(SampleDirection), sampleDirection))
|
||||||
|
{
|
||||||
|
throw new InvalidEnumArgumentException("sampleDirection", (int)sampleDirection, typeof(SampleDirection));
|
||||||
|
}
|
||||||
|
if (api == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("api");
|
||||||
|
}
|
||||||
|
Type type;
|
||||||
|
if (ActualHttpMessageTypes.TryGetValue(new HelpPageSampleKey(sampleDirection, controllerName, actionName, parameterNames), out type) ||
|
||||||
|
ActualHttpMessageTypes.TryGetValue(new HelpPageSampleKey(sampleDirection, controllerName, actionName, new[] { "*" }), out type))
|
||||||
|
{
|
||||||
|
// Re-compute the supported formatters based on type
|
||||||
|
Collection<MediaTypeFormatter> newFormatters = new Collection<MediaTypeFormatter>();
|
||||||
|
foreach (var formatter in api.ActionDescriptor.Configuration.Formatters)
|
||||||
|
{
|
||||||
|
if (IsFormatSupported(sampleDirection, formatter, type))
|
||||||
|
{
|
||||||
|
newFormatters.Add(formatter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
formatters = newFormatters;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (sampleDirection)
|
||||||
|
{
|
||||||
|
case SampleDirection.Request:
|
||||||
|
ApiParameterDescription requestBodyParameter = api.ParameterDescriptions.FirstOrDefault(p => p.Source == ApiParameterSource.FromBody);
|
||||||
|
type = requestBodyParameter == null ? null : requestBodyParameter.ParameterDescriptor.ParameterType;
|
||||||
|
formatters = api.SupportedRequestBodyFormatters;
|
||||||
|
break;
|
||||||
|
case SampleDirection.Response:
|
||||||
|
default:
|
||||||
|
type = api.ResponseDescription.ResponseType ?? api.ResponseDescription.DeclaredType;
|
||||||
|
formatters = api.SupportedResponseFormatters;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the sample object using formatter.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="formatter">The formatter.</param>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
/// <param name="type">The type.</param>
|
||||||
|
/// <param name="mediaType">Type of the media.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The exception is recorded as InvalidSample.")]
|
||||||
|
public virtual object WriteSampleObjectUsingFormatter(MediaTypeFormatter formatter, object value, Type type, MediaTypeHeaderValue mediaType)
|
||||||
|
{
|
||||||
|
if (formatter == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("formatter");
|
||||||
|
}
|
||||||
|
if (mediaType == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("mediaType");
|
||||||
|
}
|
||||||
|
|
||||||
|
object sample = String.Empty;
|
||||||
|
MemoryStream ms = null;
|
||||||
|
HttpContent content = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (formatter.CanWriteType(type))
|
||||||
|
{
|
||||||
|
ms = new MemoryStream();
|
||||||
|
content = new ObjectContent(type, value, formatter, mediaType);
|
||||||
|
formatter.WriteToStreamAsync(type, value, ms, content, null).Wait();
|
||||||
|
ms.Position = 0;
|
||||||
|
StreamReader reader = new StreamReader(ms);
|
||||||
|
string serializedSampleString = reader.ReadToEnd();
|
||||||
|
if (mediaType.MediaType.ToUpperInvariant().Contains("XML"))
|
||||||
|
{
|
||||||
|
serializedSampleString = TryFormatXml(serializedSampleString);
|
||||||
|
}
|
||||||
|
else if (mediaType.MediaType.ToUpperInvariant().Contains("JSON"))
|
||||||
|
{
|
||||||
|
serializedSampleString = TryFormatJson(serializedSampleString);
|
||||||
|
}
|
||||||
|
|
||||||
|
sample = new TextSample(serializedSampleString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sample = new InvalidSample(String.Format(
|
||||||
|
CultureInfo.CurrentCulture,
|
||||||
|
"Failed to generate the sample for media type '{0}'. Cannot use formatter '{1}' to write type '{2}'.",
|
||||||
|
mediaType,
|
||||||
|
formatter.GetType().Name,
|
||||||
|
type.Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
sample = new InvalidSample(String.Format(
|
||||||
|
CultureInfo.CurrentCulture,
|
||||||
|
"An exception has occurred while using the formatter '{0}' to generate sample for media type '{1}'. Exception message: {2}",
|
||||||
|
formatter.GetType().Name,
|
||||||
|
mediaType.MediaType,
|
||||||
|
UnwrapException(e).Message));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (ms != null)
|
||||||
|
{
|
||||||
|
ms.Dispose();
|
||||||
|
}
|
||||||
|
if (content != null)
|
||||||
|
{
|
||||||
|
content.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Exception UnwrapException(Exception exception)
|
||||||
|
{
|
||||||
|
AggregateException aggregateException = exception as AggregateException;
|
||||||
|
if (aggregateException != null)
|
||||||
|
{
|
||||||
|
return aggregateException.Flatten().InnerException;
|
||||||
|
}
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default factory for sample objects
|
||||||
|
private static object DefaultSampleObjectFactory(HelpPageSampleGenerator sampleGenerator, Type type)
|
||||||
|
{
|
||||||
|
// Try to create a default sample object
|
||||||
|
ObjectGenerator objectGenerator = new ObjectGenerator();
|
||||||
|
return objectGenerator.GenerateObject(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Handling the failure by returning the original string.")]
|
||||||
|
private static string TryFormatJson(string str)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
object parsedJson = JsonConvert.DeserializeObject(str);
|
||||||
|
return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// can't parse JSON, return the original string
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Handling the failure by returning the original string.")]
|
||||||
|
private static string TryFormatXml(string str)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XDocument xml = XDocument.Parse(str);
|
||||||
|
return xml.ToString();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// can't parse XML, return the original string
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsFormatSupported(SampleDirection sampleDirection, MediaTypeFormatter formatter, Type type)
|
||||||
|
{
|
||||||
|
switch (sampleDirection)
|
||||||
|
{
|
||||||
|
case SampleDirection.Request:
|
||||||
|
return formatter.CanReadType(type);
|
||||||
|
case SampleDirection.Response:
|
||||||
|
return formatter.CanWriteType(type);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<KeyValuePair<HelpPageSampleKey, object>> GetAllActionSamples(string controllerName, string actionName, IEnumerable<string> parameterNames, SampleDirection sampleDirection)
|
||||||
|
{
|
||||||
|
HashSet<string> parameterNamesSet = new HashSet<string>(parameterNames, StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var sample in ActionSamples)
|
||||||
|
{
|
||||||
|
HelpPageSampleKey sampleKey = sample.Key;
|
||||||
|
if (String.Equals(controllerName, sampleKey.ControllerName, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
String.Equals(actionName, sampleKey.ActionName, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
(sampleKey.ParameterNames.SetEquals(new[] { "*" }) || parameterNamesSet.SetEquals(sampleKey.ParameterNames)) &&
|
||||||
|
sampleDirection == sampleKey.SampleDirection)
|
||||||
|
{
|
||||||
|
yield return sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object WrapSampleIfString(object sample)
|
||||||
|
{
|
||||||
|
string stringSample = sample as string;
|
||||||
|
if (stringSample != null)
|
||||||
|
{
|
||||||
|
return new TextSample(stringSample);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
172
BeWoWebApi/Areas/HelpPage/SampleGeneration/HelpPageSampleKey.cs
Normal file
172
BeWoWebApi/Areas/HelpPage/SampleGeneration/HelpPageSampleKey.cs
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is used to identify the place where the sample should be applied.
|
||||||
|
/// </summary>
|
||||||
|
public class HelpPageSampleKey
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="HelpPageSampleKey"/> based on media type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mediaType">The media type.</param>
|
||||||
|
public HelpPageSampleKey(MediaTypeHeaderValue mediaType)
|
||||||
|
{
|
||||||
|
if (mediaType == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("mediaType");
|
||||||
|
}
|
||||||
|
|
||||||
|
ActionName = String.Empty;
|
||||||
|
ControllerName = String.Empty;
|
||||||
|
MediaType = mediaType;
|
||||||
|
ParameterNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="HelpPageSampleKey"/> based on media type and CLR type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mediaType">The media type.</param>
|
||||||
|
/// <param name="type">The CLR type.</param>
|
||||||
|
public HelpPageSampleKey(MediaTypeHeaderValue mediaType, Type type)
|
||||||
|
: this(mediaType)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="HelpPageSampleKey"/> based on <see cref="SampleDirection"/>, controller name, action name and parameter names.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sampleDirection">The <see cref="SampleDirection"/>.</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 HelpPageSampleKey(SampleDirection sampleDirection, string controllerName, string actionName, IEnumerable<string> parameterNames)
|
||||||
|
{
|
||||||
|
if (!Enum.IsDefined(typeof(SampleDirection), sampleDirection))
|
||||||
|
{
|
||||||
|
throw new InvalidEnumArgumentException("sampleDirection", (int)sampleDirection, typeof(SampleDirection));
|
||||||
|
}
|
||||||
|
if (controllerName == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("controllerName");
|
||||||
|
}
|
||||||
|
if (actionName == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("actionName");
|
||||||
|
}
|
||||||
|
if (parameterNames == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("parameterNames");
|
||||||
|
}
|
||||||
|
|
||||||
|
ControllerName = controllerName;
|
||||||
|
ActionName = actionName;
|
||||||
|
ParameterNames = new HashSet<string>(parameterNames, StringComparer.OrdinalIgnoreCase);
|
||||||
|
SampleDirection = sampleDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="HelpPageSampleKey"/> based on media type, <see cref="SampleDirection"/>, controller name, action name and parameter names.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mediaType">The media type.</param>
|
||||||
|
/// <param name="sampleDirection">The <see cref="SampleDirection"/>.</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 HelpPageSampleKey(MediaTypeHeaderValue mediaType, SampleDirection sampleDirection, string controllerName, string actionName, IEnumerable<string> parameterNames)
|
||||||
|
: this(sampleDirection, controllerName, actionName, parameterNames)
|
||||||
|
{
|
||||||
|
if (mediaType == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("mediaType");
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaType = mediaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the controller.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The name of the controller.
|
||||||
|
/// </value>
|
||||||
|
public string ControllerName { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the action.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The name of the action.
|
||||||
|
/// </value>
|
||||||
|
public string ActionName { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the media type.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The media type.
|
||||||
|
/// </value>
|
||||||
|
public MediaTypeHeaderValue MediaType { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the parameter names.
|
||||||
|
/// </summary>
|
||||||
|
public HashSet<string> ParameterNames { get; private set; }
|
||||||
|
|
||||||
|
public Type ParameterType { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="SampleDirection"/>.
|
||||||
|
/// </summary>
|
||||||
|
public SampleDirection? SampleDirection { get; private set; }
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
HelpPageSampleKey otherKey = obj as HelpPageSampleKey;
|
||||||
|
if (otherKey == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.Equals(ControllerName, otherKey.ControllerName, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
String.Equals(ActionName, otherKey.ActionName, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
(MediaType == otherKey.MediaType || (MediaType != null && MediaType.Equals(otherKey.MediaType))) &&
|
||||||
|
ParameterType == otherKey.ParameterType &&
|
||||||
|
SampleDirection == otherKey.SampleDirection &&
|
||||||
|
ParameterNames.SetEquals(otherKey.ParameterNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
int hashCode = ControllerName.ToUpperInvariant().GetHashCode() ^ ActionName.ToUpperInvariant().GetHashCode();
|
||||||
|
if (MediaType != null)
|
||||||
|
{
|
||||||
|
hashCode ^= MediaType.GetHashCode();
|
||||||
|
}
|
||||||
|
if (SampleDirection != null)
|
||||||
|
{
|
||||||
|
hashCode ^= SampleDirection.GetHashCode();
|
||||||
|
}
|
||||||
|
if (ParameterType != null)
|
||||||
|
{
|
||||||
|
hashCode ^= ParameterType.GetHashCode();
|
||||||
|
}
|
||||||
|
foreach (string parameterName in ParameterNames)
|
||||||
|
{
|
||||||
|
hashCode ^= parameterName.ToUpperInvariant().GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
BeWoWebApi/Areas/HelpPage/SampleGeneration/ImageSample.cs
Normal file
41
BeWoWebApi/Areas/HelpPage/SampleGeneration/ImageSample.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This represents an image sample on the help page. There's a display template named ImageSample associated with this class.
|
||||||
|
/// </summary>
|
||||||
|
public class ImageSample
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ImageSample"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="src">The URL of an image.</param>
|
||||||
|
public ImageSample(string src)
|
||||||
|
{
|
||||||
|
if (src == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("src");
|
||||||
|
}
|
||||||
|
Src = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Src { get; private set; }
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
ImageSample other = obj as ImageSample;
|
||||||
|
return other != null && Src == other.Src;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Src.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
BeWoWebApi/Areas/HelpPage/SampleGeneration/InvalidSample.cs
Normal file
37
BeWoWebApi/Areas/HelpPage/SampleGeneration/InvalidSample.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This represents an invalid sample on the help page. There's a display template named InvalidSample associated with this class.
|
||||||
|
/// </summary>
|
||||||
|
public class InvalidSample
|
||||||
|
{
|
||||||
|
public InvalidSample(string errorMessage)
|
||||||
|
{
|
||||||
|
if (errorMessage == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("errorMessage");
|
||||||
|
}
|
||||||
|
ErrorMessage = errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ErrorMessage { get; private set; }
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
InvalidSample other = obj as InvalidSample;
|
||||||
|
return other != null && ErrorMessage == other.ErrorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return ErrorMessage.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return ErrorMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
456
BeWoWebApi/Areas/HelpPage/SampleGeneration/ObjectGenerator.cs
Normal file
456
BeWoWebApi/Areas/HelpPage/SampleGeneration/ObjectGenerator.cs
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class will create an object of a given type and populate it with sample data.
|
||||||
|
/// </summary>
|
||||||
|
public class ObjectGenerator
|
||||||
|
{
|
||||||
|
internal const int DefaultCollectionSize = 2;
|
||||||
|
private readonly SimpleTypeObjectGenerator SimpleObjectGenerator = new SimpleTypeObjectGenerator();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates an object for a given type. The type needs to be public, have a public default constructor and settable public properties/fields. Currently it supports the following types:
|
||||||
|
/// Simple types: <see cref="int"/>, <see cref="string"/>, <see cref="Enum"/>, <see cref="DateTime"/>, <see cref="Uri"/>, etc.
|
||||||
|
/// Complex types: POCO types.
|
||||||
|
/// Nullables: <see cref="Nullable{T}"/>.
|
||||||
|
/// Arrays: arrays of simple types or complex types.
|
||||||
|
/// Key value pairs: <see cref="KeyValuePair{TKey,TValue}"/>
|
||||||
|
/// Tuples: <see cref="Tuple{T1}"/>, <see cref="Tuple{T1,T2}"/>, etc
|
||||||
|
/// Dictionaries: <see cref="IDictionary{TKey,TValue}"/> or anything deriving from <see cref="IDictionary{TKey,TValue}"/>.
|
||||||
|
/// Collections: <see cref="IList{T}"/>, <see cref="IEnumerable{T}"/>, <see cref="ICollection{T}"/>, <see cref="IList"/>, <see cref="IEnumerable"/>, <see cref="ICollection"/> or anything deriving from <see cref="ICollection{T}"/> or <see cref="IList"/>.
|
||||||
|
/// Queryables: <see cref="IQueryable"/>, <see cref="IQueryable{T}"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type.</param>
|
||||||
|
/// <returns>An object of the given type.</returns>
|
||||||
|
public object GenerateObject(Type type)
|
||||||
|
{
|
||||||
|
return GenerateObject(type, new Dictionary<Type, object>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Here we just want to return null if anything goes wrong.")]
|
||||||
|
private object GenerateObject(Type type, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (SimpleTypeObjectGenerator.CanGenerateObject(type))
|
||||||
|
{
|
||||||
|
return SimpleObjectGenerator.GenerateObject(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.IsArray)
|
||||||
|
{
|
||||||
|
return GenerateArray(type, DefaultCollectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.IsGenericType)
|
||||||
|
{
|
||||||
|
return GenerateGenericType(type, DefaultCollectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == typeof(IDictionary))
|
||||||
|
{
|
||||||
|
return GenerateDictionary(typeof(Hashtable), DefaultCollectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(IDictionary).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
return GenerateDictionary(type, DefaultCollectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == typeof(IList) ||
|
||||||
|
type == typeof(IEnumerable) ||
|
||||||
|
type == typeof(ICollection))
|
||||||
|
{
|
||||||
|
return GenerateCollection(typeof(ArrayList), DefaultCollectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(IList).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
return GenerateCollection(type, DefaultCollectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == typeof(IQueryable))
|
||||||
|
{
|
||||||
|
return GenerateQueryable(type, DefaultCollectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.IsEnum)
|
||||||
|
{
|
||||||
|
return GenerateEnum(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.IsPublic || type.IsNestedPublic)
|
||||||
|
{
|
||||||
|
return GenerateComplexObject(type, createdObjectReferences);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Returns null if anything fails
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GenerateGenericType(Type type, int collectionSize, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
Type genericTypeDefinition = type.GetGenericTypeDefinition();
|
||||||
|
if (genericTypeDefinition == typeof(Nullable<>))
|
||||||
|
{
|
||||||
|
return GenerateNullable(type, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (genericTypeDefinition == typeof(KeyValuePair<,>))
|
||||||
|
{
|
||||||
|
return GenerateKeyValuePair(type, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsTuple(genericTypeDefinition))
|
||||||
|
{
|
||||||
|
return GenerateTuple(type, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type[] genericArguments = type.GetGenericArguments();
|
||||||
|
if (genericArguments.Length == 1)
|
||||||
|
{
|
||||||
|
if (genericTypeDefinition == typeof(IList<>) ||
|
||||||
|
genericTypeDefinition == typeof(IEnumerable<>) ||
|
||||||
|
genericTypeDefinition == typeof(ICollection<>))
|
||||||
|
{
|
||||||
|
Type collectionType = typeof(List<>).MakeGenericType(genericArguments);
|
||||||
|
return GenerateCollection(collectionType, collectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (genericTypeDefinition == typeof(IQueryable<>))
|
||||||
|
{
|
||||||
|
return GenerateQueryable(type, collectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type closedCollectionType = typeof(ICollection<>).MakeGenericType(genericArguments[0]);
|
||||||
|
if (closedCollectionType.IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
return GenerateCollection(type, collectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (genericArguments.Length == 2)
|
||||||
|
{
|
||||||
|
if (genericTypeDefinition == typeof(IDictionary<,>))
|
||||||
|
{
|
||||||
|
Type dictionaryType = typeof(Dictionary<,>).MakeGenericType(genericArguments);
|
||||||
|
return GenerateDictionary(dictionaryType, collectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type closedDictionaryType = typeof(IDictionary<,>).MakeGenericType(genericArguments[0], genericArguments[1]);
|
||||||
|
if (closedDictionaryType.IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
return GenerateDictionary(type, collectionSize, createdObjectReferences);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.IsPublic || type.IsNestedPublic)
|
||||||
|
{
|
||||||
|
return GenerateComplexObject(type, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GenerateTuple(Type type, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
Type[] genericArgs = type.GetGenericArguments();
|
||||||
|
object[] parameterValues = new object[genericArgs.Length];
|
||||||
|
bool failedToCreateTuple = true;
|
||||||
|
ObjectGenerator objectGenerator = new ObjectGenerator();
|
||||||
|
for (int i = 0; i < genericArgs.Length; i++)
|
||||||
|
{
|
||||||
|
parameterValues[i] = objectGenerator.GenerateObject(genericArgs[i], createdObjectReferences);
|
||||||
|
failedToCreateTuple &= parameterValues[i] == null;
|
||||||
|
}
|
||||||
|
if (failedToCreateTuple)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
object result = Activator.CreateInstance(type, parameterValues);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsTuple(Type genericTypeDefinition)
|
||||||
|
{
|
||||||
|
return genericTypeDefinition == typeof(Tuple<>) ||
|
||||||
|
genericTypeDefinition == typeof(Tuple<,>) ||
|
||||||
|
genericTypeDefinition == typeof(Tuple<,,>) ||
|
||||||
|
genericTypeDefinition == typeof(Tuple<,,,>) ||
|
||||||
|
genericTypeDefinition == typeof(Tuple<,,,,>) ||
|
||||||
|
genericTypeDefinition == typeof(Tuple<,,,,,>) ||
|
||||||
|
genericTypeDefinition == typeof(Tuple<,,,,,,>) ||
|
||||||
|
genericTypeDefinition == typeof(Tuple<,,,,,,,>);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GenerateKeyValuePair(Type keyValuePairType, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
Type[] genericArgs = keyValuePairType.GetGenericArguments();
|
||||||
|
Type typeK = genericArgs[0];
|
||||||
|
Type typeV = genericArgs[1];
|
||||||
|
ObjectGenerator objectGenerator = new ObjectGenerator();
|
||||||
|
object keyObject = objectGenerator.GenerateObject(typeK, createdObjectReferences);
|
||||||
|
object valueObject = objectGenerator.GenerateObject(typeV, createdObjectReferences);
|
||||||
|
if (keyObject == null && valueObject == null)
|
||||||
|
{
|
||||||
|
// Failed to create key and values
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
object result = Activator.CreateInstance(keyValuePairType, keyObject, valueObject);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GenerateArray(Type arrayType, int size, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
Type type = arrayType.GetElementType();
|
||||||
|
Array result = Array.CreateInstance(type, size);
|
||||||
|
bool areAllElementsNull = true;
|
||||||
|
ObjectGenerator objectGenerator = new ObjectGenerator();
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
object element = objectGenerator.GenerateObject(type, createdObjectReferences);
|
||||||
|
result.SetValue(element, i);
|
||||||
|
areAllElementsNull &= element == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areAllElementsNull)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GenerateDictionary(Type dictionaryType, int size, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
Type typeK = typeof(object);
|
||||||
|
Type typeV = typeof(object);
|
||||||
|
if (dictionaryType.IsGenericType)
|
||||||
|
{
|
||||||
|
Type[] genericArgs = dictionaryType.GetGenericArguments();
|
||||||
|
typeK = genericArgs[0];
|
||||||
|
typeV = genericArgs[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
object result = Activator.CreateInstance(dictionaryType);
|
||||||
|
MethodInfo addMethod = dictionaryType.GetMethod("Add") ?? dictionaryType.GetMethod("TryAdd");
|
||||||
|
MethodInfo containsMethod = dictionaryType.GetMethod("Contains") ?? dictionaryType.GetMethod("ContainsKey");
|
||||||
|
ObjectGenerator objectGenerator = new ObjectGenerator();
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
object newKey = objectGenerator.GenerateObject(typeK, createdObjectReferences);
|
||||||
|
if (newKey == null)
|
||||||
|
{
|
||||||
|
// Cannot generate a valid key
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool containsKey = (bool)containsMethod.Invoke(result, new object[] { newKey });
|
||||||
|
if (!containsKey)
|
||||||
|
{
|
||||||
|
object newValue = objectGenerator.GenerateObject(typeV, createdObjectReferences);
|
||||||
|
addMethod.Invoke(result, new object[] { newKey, newValue });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GenerateEnum(Type enumType)
|
||||||
|
{
|
||||||
|
Array possibleValues = Enum.GetValues(enumType);
|
||||||
|
if (possibleValues.Length > 0)
|
||||||
|
{
|
||||||
|
return possibleValues.GetValue(0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GenerateQueryable(Type queryableType, int size, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
bool isGeneric = queryableType.IsGenericType;
|
||||||
|
object list;
|
||||||
|
if (isGeneric)
|
||||||
|
{
|
||||||
|
Type listType = typeof(List<>).MakeGenericType(queryableType.GetGenericArguments());
|
||||||
|
list = GenerateCollection(listType, size, createdObjectReferences);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list = GenerateArray(typeof(object[]), size, createdObjectReferences);
|
||||||
|
}
|
||||||
|
if (list == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (isGeneric)
|
||||||
|
{
|
||||||
|
Type argumentType = typeof(IEnumerable<>).MakeGenericType(queryableType.GetGenericArguments());
|
||||||
|
MethodInfo asQueryableMethod = typeof(Queryable).GetMethod("AsQueryable", new[] { argumentType });
|
||||||
|
return asQueryableMethod.Invoke(null, new[] { list });
|
||||||
|
}
|
||||||
|
|
||||||
|
return Queryable.AsQueryable((IEnumerable)list);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GenerateCollection(Type collectionType, int size, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
Type type = collectionType.IsGenericType ?
|
||||||
|
collectionType.GetGenericArguments()[0] :
|
||||||
|
typeof(object);
|
||||||
|
object result = Activator.CreateInstance(collectionType);
|
||||||
|
MethodInfo addMethod = collectionType.GetMethod("Add");
|
||||||
|
bool areAllElementsNull = true;
|
||||||
|
ObjectGenerator objectGenerator = new ObjectGenerator();
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
object element = objectGenerator.GenerateObject(type, createdObjectReferences);
|
||||||
|
addMethod.Invoke(result, new object[] { element });
|
||||||
|
areAllElementsNull &= element == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areAllElementsNull)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GenerateNullable(Type nullableType, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
Type type = nullableType.GetGenericArguments()[0];
|
||||||
|
ObjectGenerator objectGenerator = new ObjectGenerator();
|
||||||
|
return objectGenerator.GenerateObject(type, createdObjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object GenerateComplexObject(Type type, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
object result = null;
|
||||||
|
|
||||||
|
if (createdObjectReferences.TryGetValue(type, out result))
|
||||||
|
{
|
||||||
|
// The object has been created already, just return it. This will handle the circular reference case.
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.IsValueType)
|
||||||
|
{
|
||||||
|
result = Activator.CreateInstance(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConstructorInfo defaultCtor = type.GetConstructor(Type.EmptyTypes);
|
||||||
|
if (defaultCtor == null)
|
||||||
|
{
|
||||||
|
// Cannot instantiate the type because it doesn't have a default constructor
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = defaultCtor.Invoke(new object[0]);
|
||||||
|
}
|
||||||
|
createdObjectReferences.Add(type, result);
|
||||||
|
SetPublicProperties(type, result, createdObjectReferences);
|
||||||
|
SetPublicFields(type, result, createdObjectReferences);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetPublicProperties(Type type, object obj, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
ObjectGenerator objectGenerator = new ObjectGenerator();
|
||||||
|
foreach (PropertyInfo property in properties)
|
||||||
|
{
|
||||||
|
if (property.CanWrite)
|
||||||
|
{
|
||||||
|
object propertyValue = objectGenerator.GenerateObject(property.PropertyType, createdObjectReferences);
|
||||||
|
property.SetValue(obj, propertyValue, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetPublicFields(Type type, object obj, Dictionary<Type, object> createdObjectReferences)
|
||||||
|
{
|
||||||
|
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
ObjectGenerator objectGenerator = new ObjectGenerator();
|
||||||
|
foreach (FieldInfo field in fields)
|
||||||
|
{
|
||||||
|
object fieldValue = objectGenerator.GenerateObject(field.FieldType, createdObjectReferences);
|
||||||
|
field.SetValue(obj, fieldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SimpleTypeObjectGenerator
|
||||||
|
{
|
||||||
|
private long _index = 0;
|
||||||
|
private static readonly Dictionary<Type, Func<long, object>> DefaultGenerators = InitializeGenerators();
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "These are simple type factories and cannot be split up.")]
|
||||||
|
private static Dictionary<Type, Func<long, object>> InitializeGenerators()
|
||||||
|
{
|
||||||
|
return new Dictionary<Type, Func<long, object>>
|
||||||
|
{
|
||||||
|
{ typeof(Boolean), index => true },
|
||||||
|
{ typeof(Byte), index => (Byte)64 },
|
||||||
|
{ typeof(Char), index => (Char)65 },
|
||||||
|
{ typeof(DateTime), index => DateTime.Now },
|
||||||
|
{ typeof(DateTimeOffset), index => new DateTimeOffset(DateTime.Now) },
|
||||||
|
{ typeof(DBNull), index => DBNull.Value },
|
||||||
|
{ typeof(Decimal), index => (Decimal)index },
|
||||||
|
{ typeof(Double), index => (Double)(index + 0.1) },
|
||||||
|
{ typeof(Guid), index => Guid.NewGuid() },
|
||||||
|
{ typeof(Int16), index => (Int16)(index % Int16.MaxValue) },
|
||||||
|
{ typeof(Int32), index => (Int32)(index % Int32.MaxValue) },
|
||||||
|
{ typeof(Int64), index => (Int64)index },
|
||||||
|
{ typeof(Object), index => new object() },
|
||||||
|
{ typeof(SByte), index => (SByte)64 },
|
||||||
|
{ typeof(Single), index => (Single)(index + 0.1) },
|
||||||
|
{
|
||||||
|
typeof(String), index =>
|
||||||
|
{
|
||||||
|
return String.Format(CultureInfo.CurrentCulture, "sample string {0}", index);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
typeof(TimeSpan), index =>
|
||||||
|
{
|
||||||
|
return TimeSpan.FromTicks(1234567);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ typeof(UInt16), index => (UInt16)(index % UInt16.MaxValue) },
|
||||||
|
{ typeof(UInt32), index => (UInt32)(index % UInt32.MaxValue) },
|
||||||
|
{ typeof(UInt64), index => (UInt64)index },
|
||||||
|
{
|
||||||
|
typeof(Uri), index =>
|
||||||
|
{
|
||||||
|
return new Uri(String.Format(CultureInfo.CurrentCulture, "http://webapihelppage{0}.com", index));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CanGenerateObject(Type type)
|
||||||
|
{
|
||||||
|
return DefaultGenerators.ContainsKey(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GenerateObject(Type type)
|
||||||
|
{
|
||||||
|
return DefaultGenerators[type](++_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace BeWoWebApi.Areas.HelpPage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the sample is used for request or response
|
||||||
|
/// </summary>
|
||||||
|
public enum SampleDirection
|
||||||
|
{
|
||||||
|
Request = 0,
|
||||||
|
Response
|
||||||
|
}
|
||||||
|
}
|
||||||
37
BeWoWebApi/Areas/HelpPage/SampleGeneration/TextSample.cs
Normal file
37
BeWoWebApi/Areas/HelpPage/SampleGeneration/TextSample.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This represents a preformatted text sample on the help page. There's a display template named TextSample associated with this class.
|
||||||
|
/// </summary>
|
||||||
|
public class TextSample
|
||||||
|
{
|
||||||
|
public TextSample(string text)
|
||||||
|
{
|
||||||
|
if (text == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("text");
|
||||||
|
}
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
TextSample other = obj as TextSample;
|
||||||
|
return other != null && Text == other.Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Text.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
BeWoWebApi/Areas/HelpPage/Views/Help/Api.cshtml
Normal file
22
BeWoWebApi/Areas/HelpPage/Views/Help/Api.cshtml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
@using System.Web.Http
|
||||||
|
@using BeWoWebApi.Areas.HelpPage.Models
|
||||||
|
@model HelpPageApiModel
|
||||||
|
|
||||||
|
@{
|
||||||
|
var description = Model.ApiDescription;
|
||||||
|
ViewBag.Title = description.HttpMethod.Method + " " + description.RelativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
<link type="text/css" href="~/Areas/HelpPage/HelpPage.css" rel="stylesheet" />
|
||||||
|
<div id="body" class="help-page">
|
||||||
|
<section class="featured">
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<p>
|
||||||
|
@Html.ActionLink("Help Page Home", "Index")
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="content-wrapper main-content clear-fix">
|
||||||
|
@Html.DisplayForModel()
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
@using System.Web.Http
|
||||||
|
@using System.Web.Http.Controllers
|
||||||
|
@using System.Web.Http.Description
|
||||||
|
@using BeWoWebApi.Areas.HelpPage
|
||||||
|
@using BeWoWebApi.Areas.HelpPage.Models
|
||||||
|
@model IGrouping<HttpControllerDescriptor, ApiDescription>
|
||||||
|
|
||||||
|
@{
|
||||||
|
var controllerDocumentation = ViewBag.DocumentationProvider != null ?
|
||||||
|
ViewBag.DocumentationProvider.GetDocumentation(Model.Key) :
|
||||||
|
null;
|
||||||
|
}
|
||||||
|
|
||||||
|
<h2 id="@Model.Key.ControllerName">@Model.Key.ControllerName</h2>
|
||||||
|
@if (!String.IsNullOrEmpty(controllerDocumentation))
|
||||||
|
{
|
||||||
|
<p>@controllerDocumentation</p>
|
||||||
|
}
|
||||||
|
<table class="help-page-table">
|
||||||
|
<thead>
|
||||||
|
<tr><th>API</th><th>Description</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var api in Model)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td class="api-name"><a href="@Url.Action("Api", "Help", new { apiId = api.GetFriendlyId() })">@api.HttpMethod.Method @api.RelativePath</a></td>
|
||||||
|
<td class="api-documentation">
|
||||||
|
@if (api.Documentation != null)
|
||||||
|
{
|
||||||
|
<p>@api.Documentation</p>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p>No documentation available.</p>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@using BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
@model CollectionModelDescription
|
||||||
|
@if (Model.ElementDescription is ComplexTypeModelDescription)
|
||||||
|
{
|
||||||
|
@Html.DisplayFor(m => m.ElementDescription)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
@using BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
@model ComplexTypeModelDescription
|
||||||
|
@Html.DisplayFor(m => m.Properties, "Parameters")
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@using BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
@model DictionaryModelDescription
|
||||||
|
Dictionary of @Html.DisplayFor(m => Model.KeyModelDescription.ModelType, "ModelDescriptionLink", new { modelDescription = Model.KeyModelDescription }) [key]
|
||||||
|
and @Html.DisplayFor(m => Model.ValueModelDescription.ModelType, "ModelDescriptionLink", new { modelDescription = Model.ValueModelDescription }) [value]
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
@using BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
@model EnumTypeModelDescription
|
||||||
|
|
||||||
|
<p>Possible enumeration values:</p>
|
||||||
|
|
||||||
|
<table class="help-page-table">
|
||||||
|
<thead>
|
||||||
|
<tr><th>Name</th><th>Value</th><th>Description</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (EnumValueDescription value in Model.Values)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td class="enum-name"><b>@value.Name</b></td>
|
||||||
|
<td class="enum-value">
|
||||||
|
<p>@value.Value</p>
|
||||||
|
</td>
|
||||||
|
<td class="enum-description">
|
||||||
|
<p>@value.Documentation</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
@using System.Web.Http
|
||||||
|
@using System.Web.Http.Description
|
||||||
|
@using BeWoWebApi.Areas.HelpPage.Models
|
||||||
|
@using BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
@model HelpPageApiModel
|
||||||
|
|
||||||
|
@{
|
||||||
|
ApiDescription description = Model.ApiDescription;
|
||||||
|
}
|
||||||
|
<h1>@description.HttpMethod.Method @description.RelativePath</h1>
|
||||||
|
<div>
|
||||||
|
<p>@description.Documentation</p>
|
||||||
|
|
||||||
|
<h2>Request Information</h2>
|
||||||
|
|
||||||
|
<h3>URI Parameters</h3>
|
||||||
|
@Html.DisplayFor(m => m.UriParameters, "Parameters")
|
||||||
|
|
||||||
|
<h3>Body Parameters</h3>
|
||||||
|
|
||||||
|
<p>@Model.RequestDocumentation</p>
|
||||||
|
|
||||||
|
@if (Model.RequestModelDescription != null)
|
||||||
|
{
|
||||||
|
@Html.DisplayFor(m => m.RequestModelDescription.ModelType, "ModelDescriptionLink", new { modelDescription = Model.RequestModelDescription })
|
||||||
|
if (Model.RequestBodyParameters != null)
|
||||||
|
{
|
||||||
|
@Html.DisplayFor(m => m.RequestBodyParameters, "Parameters")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p>None.</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (Model.SampleRequests.Count > 0)
|
||||||
|
{
|
||||||
|
<h3>Request Formats</h3>
|
||||||
|
@Html.DisplayFor(m => m.SampleRequests, "Samples")
|
||||||
|
}
|
||||||
|
|
||||||
|
<h2>Response Information</h2>
|
||||||
|
|
||||||
|
<h3>Resource Description</h3>
|
||||||
|
|
||||||
|
<p>@description.ResponseDescription.Documentation</p>
|
||||||
|
|
||||||
|
@if (Model.ResourceDescription != null)
|
||||||
|
{
|
||||||
|
@Html.DisplayFor(m => m.ResourceDescription.ModelType, "ModelDescriptionLink", new { modelDescription = Model.ResourceDescription })
|
||||||
|
if (Model.ResourceProperties != null)
|
||||||
|
{
|
||||||
|
@Html.DisplayFor(m => m.ResourceProperties, "Parameters")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p>None.</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (Model.SampleResponses.Count > 0)
|
||||||
|
{
|
||||||
|
<h3>Response Formats</h3>
|
||||||
|
@Html.DisplayFor(m => m.SampleResponses, "Samples")
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@using BeWoWebApi.Areas.HelpPage
|
||||||
|
@model ImageSample
|
||||||
|
|
||||||
|
<img src="@Model.Src" />
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
@using BeWoWebApi.Areas.HelpPage
|
||||||
|
@model InvalidSample
|
||||||
|
|
||||||
|
@if (HttpContext.Current.IsDebuggingEnabled)
|
||||||
|
{
|
||||||
|
<div class="warning-message-container">
|
||||||
|
<p>@Model.ErrorMessage</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p>Sample not available.</p>
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@using BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
@model KeyValuePairModelDescription
|
||||||
|
Pair of @Html.DisplayFor(m => Model.KeyModelDescription.ModelType, "ModelDescriptionLink", new { modelDescription = Model.KeyModelDescription }) [key]
|
||||||
|
and @Html.DisplayFor(m => Model.ValueModelDescription.ModelType, "ModelDescriptionLink", new { modelDescription = Model.ValueModelDescription }) [value]
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
@using BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
@model Type
|
||||||
|
@{
|
||||||
|
ModelDescription modelDescription = ViewBag.modelDescription;
|
||||||
|
if (modelDescription is ComplexTypeModelDescription || modelDescription is EnumTypeModelDescription)
|
||||||
|
{
|
||||||
|
if (Model == typeof(Object))
|
||||||
|
{
|
||||||
|
@:Object
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@Html.ActionLink(modelDescription.Name, "ResourceModel", "Help", new { modelName = modelDescription.Name }, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (modelDescription is CollectionModelDescription)
|
||||||
|
{
|
||||||
|
var collectionDescription = modelDescription as CollectionModelDescription;
|
||||||
|
var elementDescription = collectionDescription.ElementDescription;
|
||||||
|
@:Collection of @Html.DisplayFor(m => elementDescription.ModelType, "ModelDescriptionLink", new { modelDescription = elementDescription })
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@Html.DisplayFor(m => modelDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
@using System.Collections.Generic
|
||||||
|
@using System.Collections.ObjectModel
|
||||||
|
@using System.Web.Http.Description
|
||||||
|
@using System.Threading
|
||||||
|
@using BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
@model IList<ParameterDescription>
|
||||||
|
|
||||||
|
@if (Model.Count > 0)
|
||||||
|
{
|
||||||
|
<table class="help-page-table">
|
||||||
|
<thead>
|
||||||
|
<tr><th>Name</th><th>Description</th><th>Type</th><th>Additional information</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (ParameterDescription parameter in Model)
|
||||||
|
{
|
||||||
|
ModelDescription modelDescription = parameter.TypeDescription;
|
||||||
|
<tr>
|
||||||
|
<td class="parameter-name">@parameter.Name</td>
|
||||||
|
<td class="parameter-documentation">
|
||||||
|
<p>@parameter.Documentation</p>
|
||||||
|
</td>
|
||||||
|
<td class="parameter-type">
|
||||||
|
@Html.DisplayFor(m => modelDescription.ModelType, "ModelDescriptionLink", new { modelDescription = modelDescription })
|
||||||
|
</td>
|
||||||
|
<td class="parameter-annotations">
|
||||||
|
@if (parameter.Annotations.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var annotation in parameter.Annotations)
|
||||||
|
{
|
||||||
|
<p>@annotation.Documentation</p>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p>None.</p>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p>None.</p>
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
@using System.Net.Http.Headers
|
||||||
|
@model Dictionary<MediaTypeHeaderValue, object>
|
||||||
|
|
||||||
|
@{
|
||||||
|
// Group the samples into a single tab if they are the same.
|
||||||
|
Dictionary<string, object> samples = Model.GroupBy(pair => pair.Value).ToDictionary(
|
||||||
|
pair => String.Join(", ", pair.Select(m => m.Key.ToString()).ToArray()),
|
||||||
|
pair => pair.Key);
|
||||||
|
var mediaTypes = samples.Keys;
|
||||||
|
}
|
||||||
|
<div>
|
||||||
|
@foreach (var mediaType in mediaTypes)
|
||||||
|
{
|
||||||
|
<h4 class="sample-header">@mediaType</h4>
|
||||||
|
<div class="sample-content">
|
||||||
|
<span><b>Sample:</b></span>
|
||||||
|
@{
|
||||||
|
var sample = samples[mediaType];
|
||||||
|
if (sample == null)
|
||||||
|
{
|
||||||
|
<p>Sample not available.</p>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@Html.DisplayFor(s => sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
@using BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
@model SimpleTypeModelDescription
|
||||||
|
@Model.Documentation
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@using BeWoWebApi.Areas.HelpPage
|
||||||
|
@model TextSample
|
||||||
|
|
||||||
|
<pre class="wrapped">
|
||||||
|
@Model.Text
|
||||||
|
</pre>
|
||||||
38
BeWoWebApi/Areas/HelpPage/Views/Help/Index.cshtml
Normal file
38
BeWoWebApi/Areas/HelpPage/Views/Help/Index.cshtml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
@using System.Web.Http
|
||||||
|
@using System.Web.Http.Controllers
|
||||||
|
@using System.Web.Http.Description
|
||||||
|
@using System.Collections.ObjectModel
|
||||||
|
@using BeWoWebApi.Areas.HelpPage.Models
|
||||||
|
@model Collection<ApiDescription>
|
||||||
|
|
||||||
|
@{
|
||||||
|
ViewBag.Title = "ASP.NET Web API Help Page";
|
||||||
|
|
||||||
|
// Group APIs by controller
|
||||||
|
ILookup<HttpControllerDescriptor, ApiDescription> apiGroups = Model.ToLookup(api => api.ActionDescriptor.ControllerDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
<link type="text/css" href="~/Areas/HelpPage/HelpPage.css" rel="stylesheet" />
|
||||||
|
<header class="help-page">
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<div class="float-left">
|
||||||
|
<h1>@ViewBag.Title</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div id="body" class="help-page">
|
||||||
|
<section class="featured">
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<h2>Introduction</h2>
|
||||||
|
<p>
|
||||||
|
Provide a general description of your APIs here.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="content-wrapper main-content clear-fix">
|
||||||
|
@foreach (var group in apiGroups)
|
||||||
|
{
|
||||||
|
@Html.DisplayFor(m => group, "ApiGroup")
|
||||||
|
}
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
19
BeWoWebApi/Areas/HelpPage/Views/Help/ResourceModel.cshtml
Normal file
19
BeWoWebApi/Areas/HelpPage/Views/Help/ResourceModel.cshtml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
@using System.Web.Http
|
||||||
|
@using BeWoWebApi.Areas.HelpPage.ModelDescriptions
|
||||||
|
@model ModelDescription
|
||||||
|
|
||||||
|
<link type="text/css" href="~/Areas/HelpPage/HelpPage.css" rel="stylesheet" />
|
||||||
|
<div id="body" class="help-page">
|
||||||
|
<section class="featured">
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<p>
|
||||||
|
@Html.ActionLink("Help Page Home", "Index")
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<h1>@Model.Name</h1>
|
||||||
|
<p>@Model.Documentation</p>
|
||||||
|
<section class="content-wrapper main-content clear-fix">
|
||||||
|
@Html.DisplayFor(m => Model)
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
12
BeWoWebApi/Areas/HelpPage/Views/Shared/_Layout.cshtml
Normal file
12
BeWoWebApi/Areas/HelpPage/Views/Shared/_Layout.cshtml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<title>@ViewBag.Title</title>
|
||||||
|
@RenderSection("scripts", required: false)
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
@RenderBody()
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
41
BeWoWebApi/Areas/HelpPage/Views/Web.config
Normal file
41
BeWoWebApi/Areas/HelpPage/Views/Web.config
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<configuration>
|
||||||
|
<configSections>
|
||||||
|
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
|
||||||
|
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
|
||||||
|
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
|
||||||
|
</sectionGroup>
|
||||||
|
</configSections>
|
||||||
|
|
||||||
|
<system.web.webPages.razor>
|
||||||
|
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
|
||||||
|
<pages pageBaseType="System.Web.Mvc.WebViewPage">
|
||||||
|
<namespaces>
|
||||||
|
<add namespace="System.Web.Mvc" />
|
||||||
|
<add namespace="System.Web.Mvc.Ajax" />
|
||||||
|
<add namespace="System.Web.Mvc.Html" />
|
||||||
|
<add namespace="System.Web.Routing" />
|
||||||
|
</namespaces>
|
||||||
|
</pages>
|
||||||
|
</system.web.webPages.razor>
|
||||||
|
|
||||||
|
<appSettings>
|
||||||
|
<add key="webpages:Enabled" value="false" />
|
||||||
|
</appSettings>
|
||||||
|
|
||||||
|
<system.web>
|
||||||
|
<compilation debug="true">
|
||||||
|
<assemblies>
|
||||||
|
<add assembly="System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
|
</assemblies>
|
||||||
|
</compilation>
|
||||||
|
</system.web>
|
||||||
|
|
||||||
|
<system.webServer>
|
||||||
|
<handlers>
|
||||||
|
<remove name="BlockViewHandler"/>
|
||||||
|
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
|
||||||
|
</handlers>
|
||||||
|
</system.webServer>
|
||||||
|
</configuration>
|
||||||
4
BeWoWebApi/Areas/HelpPage/Views/_ViewStart.cshtml
Normal file
4
BeWoWebApi/Areas/HelpPage/Views/_ViewStart.cshtml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
@{
|
||||||
|
// Change the Layout path below to blend the look and feel of the help page with your existing web pages
|
||||||
|
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||||
|
}
|
||||||
161
BeWoWebApi/Areas/HelpPage/XmlDocumentationProvider.cs
Normal file
161
BeWoWebApi/Areas/HelpPage/XmlDocumentationProvider.cs
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Web.Http.Controllers;
|
||||||
|
using System.Web.Http.Description;
|
||||||
|
using System.Xml.XPath;
|
||||||
|
using BeWoWebApi.Areas.HelpPage.ModelDescriptions;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Areas.HelpPage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A custom <see cref="IDocumentationProvider"/> that reads the API documentation from an XML documentation file.
|
||||||
|
/// </summary>
|
||||||
|
public class XmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
|
||||||
|
{
|
||||||
|
private XPathNavigator _documentNavigator;
|
||||||
|
private const string TypeExpression = "/doc/members/member[@name='T:{0}']";
|
||||||
|
private const string MethodExpression = "/doc/members/member[@name='M:{0}']";
|
||||||
|
private const string PropertyExpression = "/doc/members/member[@name='P:{0}']";
|
||||||
|
private const string FieldExpression = "/doc/members/member[@name='F:{0}']";
|
||||||
|
private const string ParameterExpression = "param[@name='{0}']";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="XmlDocumentationProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="documentPath">The physical path to XML document.</param>
|
||||||
|
public XmlDocumentationProvider(string documentPath)
|
||||||
|
{
|
||||||
|
if (documentPath == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("documentPath");
|
||||||
|
}
|
||||||
|
XPathDocument xpath = new XPathDocument(documentPath);
|
||||||
|
_documentNavigator = xpath.CreateNavigator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDocumentation(HttpControllerDescriptor controllerDescriptor)
|
||||||
|
{
|
||||||
|
XPathNavigator typeNode = GetTypeNode(controllerDescriptor.ControllerType);
|
||||||
|
return GetTagValue(typeNode, "summary");
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string GetDocumentation(HttpActionDescriptor actionDescriptor)
|
||||||
|
{
|
||||||
|
XPathNavigator methodNode = GetMethodNode(actionDescriptor);
|
||||||
|
return GetTagValue(methodNode, "summary");
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string GetDocumentation(HttpParameterDescriptor parameterDescriptor)
|
||||||
|
{
|
||||||
|
ReflectedHttpParameterDescriptor reflectedParameterDescriptor = parameterDescriptor as ReflectedHttpParameterDescriptor;
|
||||||
|
if (reflectedParameterDescriptor != null)
|
||||||
|
{
|
||||||
|
XPathNavigator methodNode = GetMethodNode(reflectedParameterDescriptor.ActionDescriptor);
|
||||||
|
if (methodNode != null)
|
||||||
|
{
|
||||||
|
string parameterName = reflectedParameterDescriptor.ParameterInfo.Name;
|
||||||
|
XPathNavigator parameterNode = methodNode.SelectSingleNode(String.Format(CultureInfo.InvariantCulture, ParameterExpression, parameterName));
|
||||||
|
if (parameterNode != null)
|
||||||
|
{
|
||||||
|
return parameterNode.Value.Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetResponseDocumentation(HttpActionDescriptor actionDescriptor)
|
||||||
|
{
|
||||||
|
XPathNavigator methodNode = GetMethodNode(actionDescriptor);
|
||||||
|
return GetTagValue(methodNode, "returns");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDocumentation(MemberInfo member)
|
||||||
|
{
|
||||||
|
string memberName = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", GetTypeName(member.DeclaringType), member.Name);
|
||||||
|
string expression = member.MemberType == MemberTypes.Field ? FieldExpression : PropertyExpression;
|
||||||
|
string selectExpression = String.Format(CultureInfo.InvariantCulture, expression, memberName);
|
||||||
|
XPathNavigator propertyNode = _documentNavigator.SelectSingleNode(selectExpression);
|
||||||
|
return GetTagValue(propertyNode, "summary");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDocumentation(Type type)
|
||||||
|
{
|
||||||
|
XPathNavigator typeNode = GetTypeNode(type);
|
||||||
|
return GetTagValue(typeNode, "summary");
|
||||||
|
}
|
||||||
|
|
||||||
|
private XPathNavigator GetMethodNode(HttpActionDescriptor actionDescriptor)
|
||||||
|
{
|
||||||
|
ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor;
|
||||||
|
if (reflectedActionDescriptor != null)
|
||||||
|
{
|
||||||
|
string selectExpression = String.Format(CultureInfo.InvariantCulture, MethodExpression, GetMemberName(reflectedActionDescriptor.MethodInfo));
|
||||||
|
return _documentNavigator.SelectSingleNode(selectExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetMemberName(MethodInfo method)
|
||||||
|
{
|
||||||
|
string name = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", GetTypeName(method.DeclaringType), method.Name);
|
||||||
|
ParameterInfo[] parameters = method.GetParameters();
|
||||||
|
if (parameters.Length != 0)
|
||||||
|
{
|
||||||
|
string[] parameterTypeNames = parameters.Select(param => GetTypeName(param.ParameterType)).ToArray();
|
||||||
|
name += String.Format(CultureInfo.InvariantCulture, "({0})", String.Join(",", parameterTypeNames));
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetTagValue(XPathNavigator parentNode, string tagName)
|
||||||
|
{
|
||||||
|
if (parentNode != null)
|
||||||
|
{
|
||||||
|
XPathNavigator node = parentNode.SelectSingleNode(tagName);
|
||||||
|
if (node != null)
|
||||||
|
{
|
||||||
|
return node.Value.Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private XPathNavigator GetTypeNode(Type type)
|
||||||
|
{
|
||||||
|
string controllerTypeName = GetTypeName(type);
|
||||||
|
string selectExpression = String.Format(CultureInfo.InvariantCulture, TypeExpression, controllerTypeName);
|
||||||
|
return _documentNavigator.SelectSingleNode(selectExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetTypeName(Type type)
|
||||||
|
{
|
||||||
|
string name = type.FullName;
|
||||||
|
if (type.IsGenericType)
|
||||||
|
{
|
||||||
|
// Format the generic type name to something like: Generic{System.Int32,System.String}
|
||||||
|
Type genericType = type.GetGenericTypeDefinition();
|
||||||
|
Type[] genericArguments = type.GetGenericArguments();
|
||||||
|
string genericTypeName = genericType.FullName;
|
||||||
|
|
||||||
|
// Trim the generic parameter counts from the name
|
||||||
|
genericTypeName = genericTypeName.Substring(0, genericTypeName.IndexOf('`'));
|
||||||
|
string[] argumentTypeNames = genericArguments.Select(t => GetTypeName(t)).ToArray();
|
||||||
|
name = String.Format(CultureInfo.InvariantCulture, "{0}{{{1}}}", genericTypeName, String.Join(",", argumentTypeNames));
|
||||||
|
}
|
||||||
|
if (type.IsNested)
|
||||||
|
{
|
||||||
|
// Changing the nested type name from OuterType+InnerType to OuterType.InnerType to match the XML documentation syntax.
|
||||||
|
name = name.Replace("+", ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
130
BeWoWebApi/Attributes/BasicAuthenticationAttribute.cs
Normal file
130
BeWoWebApi/Attributes/BasicAuthenticationAttribute.cs
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Web;
|
||||||
|
using System.Web.Http.Controllers;
|
||||||
|
using System.Web.Http.Filters;
|
||||||
|
|
||||||
|
using BeWo.Data.Access;
|
||||||
|
using BeWo.Service.ServiceImplementations;
|
||||||
|
|
||||||
|
using BS.Shared;
|
||||||
|
|
||||||
|
using NHibernate.Context;
|
||||||
|
|
||||||
|
using BeWoWebApi.BeWoWepApiUtils;
|
||||||
|
using BeWoWebApi.Service;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Attributes
|
||||||
|
{
|
||||||
|
public class BasicAuthenticationAttribute : AuthorizationFilterAttribute
|
||||||
|
{
|
||||||
|
public override void OnAuthorization(HttpActionContext actionContext)
|
||||||
|
{
|
||||||
|
if(actionContext.Request.Headers.Authorization == null)
|
||||||
|
{
|
||||||
|
actionContext.Response = CreateUnauthorizedResponse(actionContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
var authToken = actionContext.Request.Headers.Authorization.Parameter;
|
||||||
|
|
||||||
|
var decodedAuthToken = Encoding.UTF8.GetString(Convert.FromBase64String(authToken));
|
||||||
|
|
||||||
|
var userNamePasswordArray = decodedAuthToken.Split(':');
|
||||||
|
|
||||||
|
var userName = userNamePasswordArray[0];
|
||||||
|
var password = userNamePasswordArray[1];
|
||||||
|
var tenant = string.Empty;
|
||||||
|
|
||||||
|
if(actionContext.Request.Headers.TryGetValues(BeWoWebApiUtils.TenantKey, out var tenantValues))
|
||||||
|
{
|
||||||
|
var values = tenantValues as string[] ?? tenantValues.ToArray();
|
||||||
|
|
||||||
|
if(values.Length == 1)
|
||||||
|
{
|
||||||
|
tenant = values.FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var isValid = false;
|
||||||
|
|
||||||
|
if(!string.IsNullOrWhiteSpace(tenant))
|
||||||
|
{
|
||||||
|
isValid = AuthenticateUser(userName, password, tenant);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isValid)
|
||||||
|
{
|
||||||
|
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(userName), null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
actionContext.Response = CreateUnauthorizedResponse(actionContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpResponseMessage CreateUnauthorizedResponse(HttpActionContext actionContext)
|
||||||
|
{
|
||||||
|
return actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool AuthenticateUser(string userName, string password, string tenant)
|
||||||
|
{
|
||||||
|
var isValid = false;
|
||||||
|
|
||||||
|
Thread.CurrentThread.CurrentCulture = new CultureInfo(BeWoWebApiUtils.GermanCultureInfo);
|
||||||
|
|
||||||
|
WebApiApplication.InitializeSessionFactory(tenant);
|
||||||
|
var sessionFactory = WebApiApplication.SessionFactory;
|
||||||
|
|
||||||
|
if (sessionFactory != null && !HttpContext.Current.Items.Contains(BeWoWebApiUtils.HibernateSessionKey))
|
||||||
|
{
|
||||||
|
var session = WebApiApplication.SessionFactory.OpenSession();
|
||||||
|
|
||||||
|
HttpContext.Current.Items.Add(BeWoWebApiUtils.HibernateSessionKey, session);
|
||||||
|
|
||||||
|
CurrentSessionContext.Bind(session);
|
||||||
|
session.BeginTransaction();
|
||||||
|
|
||||||
|
var userService = new UserServiceImp();
|
||||||
|
|
||||||
|
if (userService.IsUserValid(userName, password, null, BeWoWebApiUtils.ClientId, false) == UserValidationResult.UserValid)
|
||||||
|
{
|
||||||
|
var user = DAOFactory.UserDAO.FindUserByLoginName(userName);
|
||||||
|
|
||||||
|
if (user != null && DAOFactory.UserDAO.CheckPassword(user, password))
|
||||||
|
{
|
||||||
|
WebApiSessionFacade.Tenant = tenant;
|
||||||
|
WebApiSessionFacade.LoggedInUser = user;
|
||||||
|
isValid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasBind = CurrentSessionContext.HasBind(WebApiApplication.SessionFactory);
|
||||||
|
|
||||||
|
if (hasBind)
|
||||||
|
{
|
||||||
|
var transaction = session.Transaction;
|
||||||
|
|
||||||
|
if (transaction != null && transaction.IsActive)
|
||||||
|
{
|
||||||
|
transaction.Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
session = CurrentSessionContext.Unbind(WebApiApplication.SessionFactory);
|
||||||
|
|
||||||
|
session.Close();
|
||||||
|
|
||||||
|
HttpContext.Current.Items.Remove(BeWoWebApiUtils.HibernateSessionKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System.Web;
|
||||||
|
using System.Web.Http.Controllers;
|
||||||
|
using System.Web.Http.Filters;
|
||||||
|
using NHibernate.Context;
|
||||||
|
using BeWoWebApi.BeWoWepApiUtils;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Attributes
|
||||||
|
{
|
||||||
|
public class NHibernateSessionManagementAttribute : ActionFilterAttribute
|
||||||
|
{
|
||||||
|
public override void OnActionExecuting(HttpActionContext actionContext)
|
||||||
|
{
|
||||||
|
if (WebApiApplication.SessionFactory != null && !HttpContext.Current.Items.Contains(BeWoWebApiUtils.HibernateSessionKey))
|
||||||
|
{
|
||||||
|
var session = WebApiApplication.SessionFactory.OpenSession();
|
||||||
|
|
||||||
|
HttpContext.Current.Items.Add(BeWoWebApiUtils.HibernateSessionKey, session);
|
||||||
|
|
||||||
|
CurrentSessionContext.Bind(session);
|
||||||
|
session.BeginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnActionExecuting(actionContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
|
||||||
|
{
|
||||||
|
var hasBind = CurrentSessionContext.HasBind(WebApiApplication.SessionFactory);
|
||||||
|
|
||||||
|
if (hasBind)
|
||||||
|
{
|
||||||
|
var session = WebApiApplication.SessionFactory.GetCurrentSession();
|
||||||
|
var transaction = session.Transaction;
|
||||||
|
|
||||||
|
if (transaction != null && transaction.IsActive)
|
||||||
|
{
|
||||||
|
transaction.Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
session = CurrentSessionContext.Unbind(WebApiApplication.SessionFactory);
|
||||||
|
|
||||||
|
session.Close();
|
||||||
|
|
||||||
|
HttpContext.Current.Items.Remove(BeWoWebApiUtils.HibernateSessionKey);
|
||||||
|
|
||||||
|
base.OnActionExecuted(actionExecutedContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
336
BeWoWebApi/BeWoWebApi.csproj
Normal file
336
BeWoWebApi/BeWoWebApi.csproj
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.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>
|
||||||
|
<ProductVersion>
|
||||||
|
</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{82254AC8-15C9-4BDD-B88E-04B95168CEEB}</ProjectGuid>
|
||||||
|
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>BeWoWebApi</RootNamespace>
|
||||||
|
<AssemblyName>BeWoWebApi</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<MvcBuildViews>false</MvcBuildViews>
|
||||||
|
<UseIISExpress>true</UseIISExpress>
|
||||||
|
<Use64BitIISExpress />
|
||||||
|
<IISExpressSSLPort>44366</IISExpressSSLPort>
|
||||||
|
<IISExpressAnonymousAuthentication />
|
||||||
|
<IISExpressWindowsAuthentication />
|
||||||
|
<IISExpressUseClassicPipelineMode />
|
||||||
|
<UseGlobalApplicationHostFile />
|
||||||
|
<NuGetPackageImportStamp>
|
||||||
|
</NuGetPackageImportStamp>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Castle.Core">
|
||||||
|
<HintPath>..\BeWoPlanerMobil\bin\Castle.Core.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Castle.DynamicProxy">
|
||||||
|
<HintPath>..\BeWoPlanerMobil\bin\Castle.DynamicProxy.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Castle.DynamicProxy2">
|
||||||
|
<HintPath>..\BeWoPlanerMobil\bin\Castle.DynamicProxy2.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="log4net">
|
||||||
|
<HintPath>..\BeWoPlanerMobil\bin\log4net.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="MySql.Data">
|
||||||
|
<HintPath>..\BeWoPlanerMobil\bin\MySql.Data.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="NHibernate">
|
||||||
|
<HintPath>..\BeWoPlanerMobil\bin\NHibernate.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="NHibernate.ByteCode.Castle">
|
||||||
|
<HintPath>..\BeWoPlanerMobil\bin\NHibernate.ByteCode.Castle.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="RestSharp, Version=106.0.0.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\RestSharp.106.10.1\lib\net452\RestSharp.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.ServiceModel" />
|
||||||
|
<Reference Include="System.Web.Entity" />
|
||||||
|
<Reference Include="System.Web.ApplicationServices" />
|
||||||
|
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Web" />
|
||||||
|
<Reference Include="System.Web.Abstractions" />
|
||||||
|
<Reference Include="System.Web.Routing" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="System.Configuration" />
|
||||||
|
<Reference Include="System.Runtime.Serialization" />
|
||||||
|
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<Private>True</Private>
|
||||||
|
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Net.Http">
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Net.Http.WebRequest">
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<Private>True</Private>
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.Helpers.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web.Http, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.7\lib\net45\System.Web.Http.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web.Http.WebHost, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.7\lib\net45\System.Web.Http.WebHost.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<Private>True</Private>
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.Mvc.5.2.7\lib\net45\System.Web.Mvc.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web.Optimization">
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<Private>True</Private>
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.Razor.3.2.7\lib\net45\System.Web.Razor.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<Private>True</Private>
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<Private>True</Private>
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<Private>True</Private>
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="WebGrease">
|
||||||
|
<Private>True</Private>
|
||||||
|
<HintPath>..\packages\WebGrease.1.6.0\lib\WebGrease.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Antlr3.Runtime">
|
||||||
|
<Private>True</Private>
|
||||||
|
<HintPath>..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform">
|
||||||
|
<HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="App_Start\BundleConfig.cs" />
|
||||||
|
<Compile Include="App_Start\FilterConfig.cs" />
|
||||||
|
<Compile Include="App_Start\RouteConfig.cs" />
|
||||||
|
<Compile Include="App_Start\WebApiConfig.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ApiDescriptionExtensions.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\App_Start\HelpPageConfig.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\Controllers\HelpController.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\HelpPageAreaRegistration.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\HelpPageConfigurationExtensions.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\CollectionModelDescription.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\ComplexTypeModelDescription.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\DictionaryModelDescription.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\EnumTypeModelDescription.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\EnumValueDescription.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\IModelDocumentationProvider.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\KeyValuePairModelDescription.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\ModelDescription.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\ModelDescriptionGenerator.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\ModelNameAttribute.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\ModelNameHelper.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\ParameterAnnotation.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\ParameterDescription.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\ModelDescriptions\SimpleTypeModelDescription.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\Models\HelpPageApiModel.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\SampleGeneration\HelpPageSampleGenerator.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\SampleGeneration\HelpPageSampleKey.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\SampleGeneration\ImageSample.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\SampleGeneration\InvalidSample.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\SampleGeneration\ObjectGenerator.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\SampleGeneration\SampleDirection.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\SampleGeneration\TextSample.cs" />
|
||||||
|
<Compile Include="Areas\HelpPage\XmlDocumentationProvider.cs" />
|
||||||
|
<Compile Include="Attributes\BasicAuthenticationAttribute.cs" />
|
||||||
|
<Compile Include="Attributes\NHibernateSessionManagementAttribute.cs" />
|
||||||
|
<Compile Include="BeWoWepApiUtils\BeWoWebApiUtils.cs" />
|
||||||
|
<Compile Include="Controllers\BeWoUserWebApiController.cs" />
|
||||||
|
<Compile Include="Controllers\BeWoWebApiBaseController.cs" />
|
||||||
|
<Compile Include="Controllers\HomeController.cs" />
|
||||||
|
<Compile Include="Controllers\LoginWebApiController.cs" />
|
||||||
|
<Compile Include="Controllers\ValuesController.cs" />
|
||||||
|
<Compile Include="Global.asax.cs">
|
||||||
|
<DependentUpon>Global.asax</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Service\WebApiSessionFacade.cs" />
|
||||||
|
<Compile Include="Service\WebApiUpdInsInterceptor.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Areas\HelpPage\HelpPage.css" />
|
||||||
|
<Content Include="Content\bootstrap-theme.css" />
|
||||||
|
<Content Include="Content\bootstrap-theme.min.css" />
|
||||||
|
<Content Include="Content\bootstrap.css" />
|
||||||
|
<Content Include="Content\bootstrap.min.css" />
|
||||||
|
<Content Include="favicon.ico" />
|
||||||
|
<Content Include="fonts\glyphicons-halflings-regular.svg" />
|
||||||
|
<Content Include="Global.asax" />
|
||||||
|
<Content Include="Scripts\bootstrap.js" />
|
||||||
|
<Content Include="Scripts\bootstrap.min.js" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Web.config" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Shared\_Layout.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\ResourceModel.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\Index.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\TextSample.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\SimpleTypeModelDescription.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\Samples.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\Parameters.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\ModelDescriptionLink.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\KeyValuePairModelDescription.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\InvalidSample.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\ImageSample.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\HelpPageApiModel.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\EnumTypeModelDescription.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\DictionaryModelDescription.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\ComplexTypeModelDescription.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\CollectionModelDescription.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\ApiGroup.cshtml" />
|
||||||
|
<Content Include="Areas\HelpPage\Views\Help\Api.cshtml" />
|
||||||
|
<None Include="Scripts\jquery-3.4.1.intellisense.js" />
|
||||||
|
<Content Include="Scripts\jquery-3.4.1.js" />
|
||||||
|
<Content Include="Scripts\jquery-3.4.1.min.js" />
|
||||||
|
<Content Include="Scripts\jquery-3.4.1.slim.js" />
|
||||||
|
<Content Include="Scripts\jquery-3.4.1.slim.min.js" />
|
||||||
|
<Content Include="Scripts\modernizr-2.8.3.js" />
|
||||||
|
<Content Include="Web.config" />
|
||||||
|
<Content Include="Web.Debug.config">
|
||||||
|
<DependentUpon>Web.config</DependentUpon>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Web.Release.config">
|
||||||
|
<DependentUpon>Web.config</DependentUpon>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Areas\HelpPage\Views\_ViewStart.cshtml" />
|
||||||
|
<Content Include="Content\Site.css" />
|
||||||
|
<Content Include="Views\Web.config" />
|
||||||
|
<Content Include="Views\_ViewStart.cshtml" />
|
||||||
|
<Content Include="Views\Home\Index.cshtml" />
|
||||||
|
<Content Include="Views\Shared\Error.cshtml" />
|
||||||
|
<Content Include="Views\Shared\_Layout.cshtml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="App_Data\" />
|
||||||
|
<Folder Include="Models\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="fonts\glyphicons-halflings-regular.woff2" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="fonts\glyphicons-halflings-regular.woff" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="fonts\glyphicons-halflings-regular.ttf" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="fonts\glyphicons-halflings-regular.eot" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Content\bootstrap.min.css.map" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Content\bootstrap.css.map" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Content\bootstrap-theme.min.css.map" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Content\bootstrap-theme.css.map" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<Content Include="Scripts\jquery-3.4.1.slim.min.map" />
|
||||||
|
<Content Include="Scripts\jquery-3.4.1.min.map" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Data\Data.csproj">
|
||||||
|
<Project>{b0d73e3d-4ae7-4024-93a6-db1f46d7ccee}</Project>
|
||||||
|
<Name>Data</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\Service\Service.csproj">
|
||||||
|
<Project>{094331c3-ecee-4c89-bbfd-4c9ded89f0ef}</Project>
|
||||||
|
<Name>Service</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\Shared\Shared.csproj">
|
||||||
|
<Project>{2f50b83d-a3f0-4ec4-979a-3f9b7e3d8ed4}</Project>
|
||||||
|
<Name>Shared</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
|
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
|
||||||
|
<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
|
||||||
|
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
|
||||||
|
</Target>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<VisualStudio>
|
||||||
|
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||||
|
<WebProjectProperties>
|
||||||
|
<UseIIS>True</UseIIS>
|
||||||
|
<AutoAssignPort>True</AutoAssignPort>
|
||||||
|
<DevelopmentServerPort>56923</DevelopmentServerPort>
|
||||||
|
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||||
|
<IISUrl>https://localhost:44366/</IISUrl>
|
||||||
|
<NTLMAuthentication>False</NTLMAuthentication>
|
||||||
|
<UseCustomServer>False</UseCustomServer>
|
||||||
|
<CustomServerUrl>
|
||||||
|
</CustomServerUrl>
|
||||||
|
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||||
|
</WebProjectProperties>
|
||||||
|
</FlavorProperties>
|
||||||
|
</VisualStudio>
|
||||||
|
</ProjectExtensions>
|
||||||
|
<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\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
|
||||||
|
</Target>
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target> -->
|
||||||
|
</Project>
|
||||||
46
BeWoWebApi/BeWoWebApi.csproj.user
Normal file
46
BeWoWebApi/BeWoWebApi.csproj.user
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<UseIISExpress>true</UseIISExpress>
|
||||||
|
<Use64BitIISExpress />
|
||||||
|
<IISExpressSSLPort>44366</IISExpressSSLPort>
|
||||||
|
<IISExpressAnonymousAuthentication />
|
||||||
|
<IISExpressWindowsAuthentication />
|
||||||
|
<IISExpressUseClassicPipelineMode />
|
||||||
|
<UseGlobalApplicationHostFile />
|
||||||
|
<LastActiveSolutionConfig>Debug|Any CPU</LastActiveSolutionConfig>
|
||||||
|
<Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
|
||||||
|
<Controller_SelectedScaffolderCategoryPath>root/Controller</Controller_SelectedScaffolderCategoryPath>
|
||||||
|
<WebStackScaffolding_ControllerDialogWidth>600</WebStackScaffolding_ControllerDialogWidth>
|
||||||
|
<WebStackScaffolding_IsLayoutPageSelected>True</WebStackScaffolding_IsLayoutPageSelected>
|
||||||
|
<WebStackScaffolding_IsPartialViewSelected>False</WebStackScaffolding_IsPartialViewSelected>
|
||||||
|
<WebStackScaffolding_IsReferencingScriptLibrariesSelected>True</WebStackScaffolding_IsReferencingScriptLibrariesSelected>
|
||||||
|
<WebStackScaffolding_LayoutPageFile />
|
||||||
|
<WebStackScaffolding_IsAsyncSelected>False</WebStackScaffolding_IsAsyncSelected>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ProjectExtensions>
|
||||||
|
<VisualStudio>
|
||||||
|
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||||
|
<WebProjectProperties>
|
||||||
|
<StartPageUrl>
|
||||||
|
</StartPageUrl>
|
||||||
|
<StartAction>CurrentPage</StartAction>
|
||||||
|
<AspNetDebugging>True</AspNetDebugging>
|
||||||
|
<SilverlightDebugging>False</SilverlightDebugging>
|
||||||
|
<NativeDebugging>False</NativeDebugging>
|
||||||
|
<SQLDebugging>False</SQLDebugging>
|
||||||
|
<ExternalProgram>
|
||||||
|
</ExternalProgram>
|
||||||
|
<StartExternalURL>
|
||||||
|
</StartExternalURL>
|
||||||
|
<StartCmdLineArguments>
|
||||||
|
</StartCmdLineArguments>
|
||||||
|
<StartWorkingDirectory>
|
||||||
|
</StartWorkingDirectory>
|
||||||
|
<EnableENC>True</EnableENC>
|
||||||
|
<AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug>
|
||||||
|
</WebProjectProperties>
|
||||||
|
</FlavorProperties>
|
||||||
|
</VisualStudio>
|
||||||
|
</ProjectExtensions>
|
||||||
|
</Project>
|
||||||
14
BeWoWebApi/BeWoWepApiUtils/BeWoWebApiUtils.cs
Normal file
14
BeWoWebApi/BeWoWepApiUtils/BeWoWebApiUtils.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace BeWoWebApi.BeWoWepApiUtils
|
||||||
|
{
|
||||||
|
public class BeWoWebApiUtils
|
||||||
|
{
|
||||||
|
public static string MultitenancyPathKey => "MultitenancyPath";
|
||||||
|
public static string NHibernateConfigSessionContextClassKey => "current_session_context_class";
|
||||||
|
public static string NHibernateConfigSessionContextClassValue => "web";
|
||||||
|
public static string GermanCultureInfo => "de-DE";
|
||||||
|
public static string TenantKey => "tenant";
|
||||||
|
public static string HibernateSessionKey => "hibernateSession";
|
||||||
|
public static string ApUserKey => "apuser";
|
||||||
|
public static string ClientId => "WebApi";
|
||||||
|
}
|
||||||
|
}
|
||||||
17
BeWoWebApi/Content/Site.css
Normal file
17
BeWoWebApi/Content/Site.css
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
body {
|
||||||
|
padding-top: 50px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set padding to keep content from hitting the edges */
|
||||||
|
.body-content {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set width on the form input elements since they're 100% wide by default */
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
max-width: 280px;
|
||||||
|
}
|
||||||
587
BeWoWebApi/Content/bootstrap-theme.css
vendored
Normal file
587
BeWoWebApi/Content/bootstrap-theme.css
vendored
Normal file
@@ -0,0 +1,587 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap v3.4.1 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2019 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
*/
|
||||||
|
.btn-default,
|
||||||
|
.btn-primary,
|
||||||
|
.btn-success,
|
||||||
|
.btn-info,
|
||||||
|
.btn-warning,
|
||||||
|
.btn-danger {
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||||
|
}
|
||||||
|
.btn-default:active,
|
||||||
|
.btn-primary:active,
|
||||||
|
.btn-success:active,
|
||||||
|
.btn-info:active,
|
||||||
|
.btn-warning:active,
|
||||||
|
.btn-danger:active,
|
||||||
|
.btn-default.active,
|
||||||
|
.btn-primary.active,
|
||||||
|
.btn-success.active,
|
||||||
|
.btn-info.active,
|
||||||
|
.btn-warning.active,
|
||||||
|
.btn-danger.active {
|
||||||
|
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
|
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||||
|
}
|
||||||
|
.btn-default.disabled,
|
||||||
|
.btn-primary.disabled,
|
||||||
|
.btn-success.disabled,
|
||||||
|
.btn-info.disabled,
|
||||||
|
.btn-warning.disabled,
|
||||||
|
.btn-danger.disabled,
|
||||||
|
.btn-default[disabled],
|
||||||
|
.btn-primary[disabled],
|
||||||
|
.btn-success[disabled],
|
||||||
|
.btn-info[disabled],
|
||||||
|
.btn-warning[disabled],
|
||||||
|
.btn-danger[disabled],
|
||||||
|
fieldset[disabled] .btn-default,
|
||||||
|
fieldset[disabled] .btn-primary,
|
||||||
|
fieldset[disabled] .btn-success,
|
||||||
|
fieldset[disabled] .btn-info,
|
||||||
|
fieldset[disabled] .btn-warning,
|
||||||
|
fieldset[disabled] .btn-danger {
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.btn-default .badge,
|
||||||
|
.btn-primary .badge,
|
||||||
|
.btn-success .badge,
|
||||||
|
.btn-info .badge,
|
||||||
|
.btn-warning .badge,
|
||||||
|
.btn-danger .badge {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
.btn:active,
|
||||||
|
.btn.active {
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-default {
|
||||||
|
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
|
||||||
|
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #dbdbdb;
|
||||||
|
text-shadow: 0 1px 0 #fff;
|
||||||
|
border-color: #ccc;
|
||||||
|
}
|
||||||
|
.btn-default:hover,
|
||||||
|
.btn-default:focus {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-default:active,
|
||||||
|
.btn-default.active {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
border-color: #dbdbdb;
|
||||||
|
}
|
||||||
|
.btn-default.disabled,
|
||||||
|
.btn-default[disabled],
|
||||||
|
fieldset[disabled] .btn-default,
|
||||||
|
.btn-default.disabled:hover,
|
||||||
|
.btn-default[disabled]:hover,
|
||||||
|
fieldset[disabled] .btn-default:hover,
|
||||||
|
.btn-default.disabled:focus,
|
||||||
|
.btn-default[disabled]:focus,
|
||||||
|
fieldset[disabled] .btn-default:focus,
|
||||||
|
.btn-default.disabled.focus,
|
||||||
|
.btn-default[disabled].focus,
|
||||||
|
fieldset[disabled] .btn-default.focus,
|
||||||
|
.btn-default.disabled:active,
|
||||||
|
.btn-default[disabled]:active,
|
||||||
|
fieldset[disabled] .btn-default:active,
|
||||||
|
.btn-default.disabled.active,
|
||||||
|
.btn-default[disabled].active,
|
||||||
|
fieldset[disabled] .btn-default.active {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-primary {
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #245580;
|
||||||
|
}
|
||||||
|
.btn-primary:hover,
|
||||||
|
.btn-primary:focus {
|
||||||
|
background-color: #265a88;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-primary:active,
|
||||||
|
.btn-primary.active {
|
||||||
|
background-color: #265a88;
|
||||||
|
border-color: #245580;
|
||||||
|
}
|
||||||
|
.btn-primary.disabled,
|
||||||
|
.btn-primary[disabled],
|
||||||
|
fieldset[disabled] .btn-primary,
|
||||||
|
.btn-primary.disabled:hover,
|
||||||
|
.btn-primary[disabled]:hover,
|
||||||
|
fieldset[disabled] .btn-primary:hover,
|
||||||
|
.btn-primary.disabled:focus,
|
||||||
|
.btn-primary[disabled]:focus,
|
||||||
|
fieldset[disabled] .btn-primary:focus,
|
||||||
|
.btn-primary.disabled.focus,
|
||||||
|
.btn-primary[disabled].focus,
|
||||||
|
fieldset[disabled] .btn-primary.focus,
|
||||||
|
.btn-primary.disabled:active,
|
||||||
|
.btn-primary[disabled]:active,
|
||||||
|
fieldset[disabled] .btn-primary:active,
|
||||||
|
.btn-primary.disabled.active,
|
||||||
|
.btn-primary[disabled].active,
|
||||||
|
fieldset[disabled] .btn-primary.active {
|
||||||
|
background-color: #265a88;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-success {
|
||||||
|
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
|
||||||
|
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #3e8f3e;
|
||||||
|
}
|
||||||
|
.btn-success:hover,
|
||||||
|
.btn-success:focus {
|
||||||
|
background-color: #419641;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-success:active,
|
||||||
|
.btn-success.active {
|
||||||
|
background-color: #419641;
|
||||||
|
border-color: #3e8f3e;
|
||||||
|
}
|
||||||
|
.btn-success.disabled,
|
||||||
|
.btn-success[disabled],
|
||||||
|
fieldset[disabled] .btn-success,
|
||||||
|
.btn-success.disabled:hover,
|
||||||
|
.btn-success[disabled]:hover,
|
||||||
|
fieldset[disabled] .btn-success:hover,
|
||||||
|
.btn-success.disabled:focus,
|
||||||
|
.btn-success[disabled]:focus,
|
||||||
|
fieldset[disabled] .btn-success:focus,
|
||||||
|
.btn-success.disabled.focus,
|
||||||
|
.btn-success[disabled].focus,
|
||||||
|
fieldset[disabled] .btn-success.focus,
|
||||||
|
.btn-success.disabled:active,
|
||||||
|
.btn-success[disabled]:active,
|
||||||
|
fieldset[disabled] .btn-success:active,
|
||||||
|
.btn-success.disabled.active,
|
||||||
|
.btn-success[disabled].active,
|
||||||
|
fieldset[disabled] .btn-success.active {
|
||||||
|
background-color: #419641;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-info {
|
||||||
|
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
|
||||||
|
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #28a4c9;
|
||||||
|
}
|
||||||
|
.btn-info:hover,
|
||||||
|
.btn-info:focus {
|
||||||
|
background-color: #2aabd2;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-info:active,
|
||||||
|
.btn-info.active {
|
||||||
|
background-color: #2aabd2;
|
||||||
|
border-color: #28a4c9;
|
||||||
|
}
|
||||||
|
.btn-info.disabled,
|
||||||
|
.btn-info[disabled],
|
||||||
|
fieldset[disabled] .btn-info,
|
||||||
|
.btn-info.disabled:hover,
|
||||||
|
.btn-info[disabled]:hover,
|
||||||
|
fieldset[disabled] .btn-info:hover,
|
||||||
|
.btn-info.disabled:focus,
|
||||||
|
.btn-info[disabled]:focus,
|
||||||
|
fieldset[disabled] .btn-info:focus,
|
||||||
|
.btn-info.disabled.focus,
|
||||||
|
.btn-info[disabled].focus,
|
||||||
|
fieldset[disabled] .btn-info.focus,
|
||||||
|
.btn-info.disabled:active,
|
||||||
|
.btn-info[disabled]:active,
|
||||||
|
fieldset[disabled] .btn-info:active,
|
||||||
|
.btn-info.disabled.active,
|
||||||
|
.btn-info[disabled].active,
|
||||||
|
fieldset[disabled] .btn-info.active {
|
||||||
|
background-color: #2aabd2;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-warning {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
|
||||||
|
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #e38d13;
|
||||||
|
}
|
||||||
|
.btn-warning:hover,
|
||||||
|
.btn-warning:focus {
|
||||||
|
background-color: #eb9316;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-warning:active,
|
||||||
|
.btn-warning.active {
|
||||||
|
background-color: #eb9316;
|
||||||
|
border-color: #e38d13;
|
||||||
|
}
|
||||||
|
.btn-warning.disabled,
|
||||||
|
.btn-warning[disabled],
|
||||||
|
fieldset[disabled] .btn-warning,
|
||||||
|
.btn-warning.disabled:hover,
|
||||||
|
.btn-warning[disabled]:hover,
|
||||||
|
fieldset[disabled] .btn-warning:hover,
|
||||||
|
.btn-warning.disabled:focus,
|
||||||
|
.btn-warning[disabled]:focus,
|
||||||
|
fieldset[disabled] .btn-warning:focus,
|
||||||
|
.btn-warning.disabled.focus,
|
||||||
|
.btn-warning[disabled].focus,
|
||||||
|
fieldset[disabled] .btn-warning.focus,
|
||||||
|
.btn-warning.disabled:active,
|
||||||
|
.btn-warning[disabled]:active,
|
||||||
|
fieldset[disabled] .btn-warning:active,
|
||||||
|
.btn-warning.disabled.active,
|
||||||
|
.btn-warning[disabled].active,
|
||||||
|
fieldset[disabled] .btn-warning.active {
|
||||||
|
background-color: #eb9316;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.btn-danger {
|
||||||
|
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
|
||||||
|
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #b92c28;
|
||||||
|
}
|
||||||
|
.btn-danger:hover,
|
||||||
|
.btn-danger:focus {
|
||||||
|
background-color: #c12e2a;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
}
|
||||||
|
.btn-danger:active,
|
||||||
|
.btn-danger.active {
|
||||||
|
background-color: #c12e2a;
|
||||||
|
border-color: #b92c28;
|
||||||
|
}
|
||||||
|
.btn-danger.disabled,
|
||||||
|
.btn-danger[disabled],
|
||||||
|
fieldset[disabled] .btn-danger,
|
||||||
|
.btn-danger.disabled:hover,
|
||||||
|
.btn-danger[disabled]:hover,
|
||||||
|
fieldset[disabled] .btn-danger:hover,
|
||||||
|
.btn-danger.disabled:focus,
|
||||||
|
.btn-danger[disabled]:focus,
|
||||||
|
fieldset[disabled] .btn-danger:focus,
|
||||||
|
.btn-danger.disabled.focus,
|
||||||
|
.btn-danger[disabled].focus,
|
||||||
|
fieldset[disabled] .btn-danger.focus,
|
||||||
|
.btn-danger.disabled:active,
|
||||||
|
.btn-danger[disabled]:active,
|
||||||
|
fieldset[disabled] .btn-danger:active,
|
||||||
|
.btn-danger.disabled.active,
|
||||||
|
.btn-danger[disabled].active,
|
||||||
|
fieldset[disabled] .btn-danger.active {
|
||||||
|
background-color: #c12e2a;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.thumbnail,
|
||||||
|
.img-thumbnail {
|
||||||
|
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||||
|
}
|
||||||
|
.dropdown-menu > li > a:hover,
|
||||||
|
.dropdown-menu > li > a:focus {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
||||||
|
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
}
|
||||||
|
.dropdown-menu > .active > a,
|
||||||
|
.dropdown-menu > .active > a:hover,
|
||||||
|
.dropdown-menu > .active > a:focus {
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
background-color: #2e6da4;
|
||||||
|
}
|
||||||
|
.navbar-default {
|
||||||
|
background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));
|
||||||
|
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||||
|
}
|
||||||
|
.navbar-default .navbar-nav > .open > a,
|
||||||
|
.navbar-default .navbar-nav > .active > a {
|
||||||
|
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
|
||||||
|
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||||
|
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||||
|
}
|
||||||
|
.navbar-brand,
|
||||||
|
.navbar-nav > li > a {
|
||||||
|
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
|
||||||
|
}
|
||||||
|
.navbar-inverse {
|
||||||
|
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
|
||||||
|
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.navbar-inverse .navbar-nav > .open > a,
|
||||||
|
.navbar-inverse .navbar-nav > .active > a {
|
||||||
|
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
|
||||||
|
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
|
||||||
|
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
.navbar-inverse .navbar-brand,
|
||||||
|
.navbar-inverse .navbar-nav > li > a {
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
.navbar-static-top,
|
||||||
|
.navbar-fixed-top,
|
||||||
|
.navbar-fixed-bottom {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.navbar .navbar-nav .open .dropdown-menu > .active > a,
|
||||||
|
.navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
|
||||||
|
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
|
||||||
|
color: #fff;
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alert {
|
||||||
|
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||||
|
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
.alert-success {
|
||||||
|
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
|
||||||
|
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #b2dba1;
|
||||||
|
}
|
||||||
|
.alert-info {
|
||||||
|
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
|
||||||
|
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #9acfea;
|
||||||
|
}
|
||||||
|
.alert-warning {
|
||||||
|
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
|
||||||
|
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #f5e79e;
|
||||||
|
}
|
||||||
|
.alert-danger {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
|
||||||
|
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #dca7a7;
|
||||||
|
}
|
||||||
|
.progress {
|
||||||
|
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
|
||||||
|
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar {
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar-success {
|
||||||
|
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
|
||||||
|
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar-info {
|
||||||
|
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
|
||||||
|
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar-warning {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
|
||||||
|
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar-danger {
|
||||||
|
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
|
||||||
|
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.progress-bar-striped {
|
||||||
|
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||||
|
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||||
|
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
|
||||||
|
}
|
||||||
|
.list-group {
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||||
|
}
|
||||||
|
.list-group-item.active,
|
||||||
|
.list-group-item.active:hover,
|
||||||
|
.list-group-item.active:focus {
|
||||||
|
text-shadow: 0 -1px 0 #286090;
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #2b669a;
|
||||||
|
}
|
||||||
|
.list-group-item.active .badge,
|
||||||
|
.list-group-item.active:hover .badge,
|
||||||
|
.list-group-item.active:focus .badge {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
.panel {
|
||||||
|
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
.panel-default > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
||||||
|
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.panel-primary > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
||||||
|
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.panel-success > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
|
||||||
|
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.panel-info > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
|
||||||
|
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.panel-warning > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
|
||||||
|
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.panel-danger > .panel-heading {
|
||||||
|
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
|
||||||
|
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
.well {
|
||||||
|
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||||
|
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
|
||||||
|
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border-color: #dcdcdc;
|
||||||
|
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
|
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=bootstrap-theme.css.map */
|
||||||
1
BeWoWebApi/Content/bootstrap-theme.css.map
Normal file
1
BeWoWebApi/Content/bootstrap-theme.css.map
Normal file
File diff suppressed because one or more lines are too long
6
BeWoWebApi/Content/bootstrap-theme.min.css
vendored
Normal file
6
BeWoWebApi/Content/bootstrap-theme.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
BeWoWebApi/Content/bootstrap-theme.min.css.map
Normal file
1
BeWoWebApi/Content/bootstrap-theme.min.css.map
Normal file
File diff suppressed because one or more lines are too long
6834
BeWoWebApi/Content/bootstrap.css
vendored
Normal file
6834
BeWoWebApi/Content/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
BeWoWebApi/Content/bootstrap.css.map
Normal file
1
BeWoWebApi/Content/bootstrap.css.map
Normal file
File diff suppressed because one or more lines are too long
6
BeWoWebApi/Content/bootstrap.min.css
vendored
Normal file
6
BeWoWebApi/Content/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
BeWoWebApi/Content/bootstrap.min.css.map
Normal file
1
BeWoWebApi/Content/bootstrap.min.css.map
Normal file
File diff suppressed because one or more lines are too long
39
BeWoWebApi/Controllers/BeWoUserWebApiController.cs
Normal file
39
BeWoWebApi/Controllers/BeWoUserWebApiController.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Web.Http;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Controllers
|
||||||
|
{
|
||||||
|
|
||||||
|
public class BeWoUserWebApiController : BeWoWebApiBaseController
|
||||||
|
{
|
||||||
|
// GET: api/BeWoUserWebApi
|
||||||
|
public IEnumerable<string> Get()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
return new string[] { "value1", "value2" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET: api/BeWoUserWebApi/5
|
||||||
|
public string Get(int id)
|
||||||
|
{
|
||||||
|
return "value";
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST: api/BeWoUserWebApi
|
||||||
|
public void Post([FromBody]string value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT: api/BeWoUserWebApi/5
|
||||||
|
public void Put(int id, [FromBody]string value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE: api/BeWoUserWebApi/5
|
||||||
|
public void Delete(int id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
BeWoWebApi/Controllers/BeWoWebApiBaseController.cs
Normal file
11
BeWoWebApi/Controllers/BeWoWebApiBaseController.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Web.Http;
|
||||||
|
using BeWoWebApi.Attributes;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Controllers
|
||||||
|
{
|
||||||
|
[BasicAuthentication]
|
||||||
|
[NHibernateSessionManagement]
|
||||||
|
public abstract class BeWoWebApiBaseController : ApiController
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
18
BeWoWebApi/Controllers/HomeController.cs
Normal file
18
BeWoWebApi/Controllers/HomeController.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Controllers
|
||||||
|
{
|
||||||
|
public class HomeController : Controller
|
||||||
|
{
|
||||||
|
public ActionResult Index()
|
||||||
|
{
|
||||||
|
ViewBag.Title = "Home Page";
|
||||||
|
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
BeWoWebApi/Controllers/LoginWebApiController.cs
Normal file
13
BeWoWebApi/Controllers/LoginWebApiController.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Web.Http;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Controllers
|
||||||
|
{
|
||||||
|
public class LoginWebApiController : BeWoWebApiBaseController
|
||||||
|
{
|
||||||
|
// POST: api/LoginWebApi
|
||||||
|
public void Post([FromBody]string value)
|
||||||
|
{
|
||||||
|
// TODO: Hier den Login durchführen, der einen bool-Wert zurückliefert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
BeWoWebApi/Controllers/ValuesController.cs
Normal file
39
BeWoWebApi/Controllers/ValuesController.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Web.Http;
|
||||||
|
|
||||||
|
namespace BeWoWebApi.Controllers
|
||||||
|
{
|
||||||
|
public class ValuesController : ApiController
|
||||||
|
{
|
||||||
|
// GET api/values
|
||||||
|
public IEnumerable<string> Get()
|
||||||
|
{
|
||||||
|
return new string[] { "value1", "value2" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET api/values/5
|
||||||
|
public string Get(int id)
|
||||||
|
{
|
||||||
|
return "value";
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST api/values
|
||||||
|
public void Post([FromBody]string value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT api/values/5
|
||||||
|
public void Put(int id, [FromBody]string value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE api/values/5
|
||||||
|
public void Delete(int id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
BeWoWebApi/Global.asax
Normal file
1
BeWoWebApi/Global.asax
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<%@ Application Codebehind="Global.asax.cs" Inherits="BeWoWebApi.WebApiApplication" Language="C#" %>
|
||||||
95
BeWoWebApi/Global.asax.cs
Normal file
95
BeWoWebApi/Global.asax.cs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
using System;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.ServiceModel;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Web;
|
||||||
|
using System.Web.Http;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
using System.Web.Optimization;
|
||||||
|
using System.Web.Routing;
|
||||||
|
using BeWoWebApi.Attributes;
|
||||||
|
using BeWoWebApi.Service;
|
||||||
|
using NHibernate;
|
||||||
|
using Configuration = NHibernate.Cfg.Configuration;
|
||||||
|
using BeWoWebApi.BeWoWepApiUtils;
|
||||||
|
using BS.Shared.Core;
|
||||||
|
|
||||||
|
namespace BeWoWebApi
|
||||||
|
{
|
||||||
|
public class WebApiApplication : HttpApplication
|
||||||
|
{
|
||||||
|
public static ISessionFactory SessionFactory
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Application_Start()
|
||||||
|
{
|
||||||
|
AreaRegistration.RegisterAllAreas();
|
||||||
|
GlobalConfiguration.Configure(WebApiConfig.Register);
|
||||||
|
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
|
||||||
|
RouteConfig.RegisterRoutes(RouteTable.Routes);
|
||||||
|
BundleConfig.RegisterBundles(BundleTable.Bundles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeSessionFactory()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var headers = Request.Headers;
|
||||||
|
|
||||||
|
if (Utils.ContainsKey(Request.Headers.AllKeys, BeWoWebApiUtils.TenantKey))
|
||||||
|
{
|
||||||
|
var tenant = headers[BeWoWebApiUtils.TenantKey];
|
||||||
|
|
||||||
|
InitializeSessionFactory(tenant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
throw new FaultException(exception.StackTrace + (exception.InnerException?.Message ?? string.Empty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void InitializeSessionFactory(string tenant)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var serverPath = HttpContext.Current.Server.MapPath(string.Empty);
|
||||||
|
|
||||||
|
var multitenancyPath = ConfigurationManager.AppSettings.Get(BeWoWebApiUtils.MultitenancyPathKey);
|
||||||
|
|
||||||
|
serverPath = Path.Combine(serverPath, multitenancyPath);
|
||||||
|
serverPath = Path.Combine(serverPath, $"{tenant}.config");
|
||||||
|
|
||||||
|
if (File.Exists(serverPath))
|
||||||
|
{
|
||||||
|
var config = new Configuration().Configure(serverPath).SetInterceptor(new WebApiUpdInsInterceptor());
|
||||||
|
config.Properties.Add(BeWoWebApiUtils.NHibernateConfigSessionContextClassKey, BeWoWebApiUtils.NHibernateConfigSessionContextClassValue);
|
||||||
|
|
||||||
|
SessionFactory = config.BuildSessionFactory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
throw new FaultException(exception.StackTrace + (exception.InnerException?.Message ?? string.Empty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Application_BeginRequest(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Thread.CurrentThread.CurrentCulture = new CultureInfo(BeWoWebApiUtils.GermanCultureInfo);
|
||||||
|
|
||||||
|
InitializeSessionFactory();
|
||||||
|
|
||||||
|
if (GlobalConfiguration.Configuration.Filters.All(filter => filter.GetType() != typeof(NHibernateSessionManagementAttribute)))
|
||||||
|
{
|
||||||
|
GlobalConfiguration.Configuration.Filters.Add(new NHibernateSessionManagementAttribute());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
BeWoWebApi/Properties/AssemblyInfo.cs
Normal file
35
BeWoWebApi/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
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("BeWoWebApi")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("BeWoWebApi")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||||
|
[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("efa58485-ad68-4b19-b761-88a2ac8fa1a7")]
|
||||||
|
|
||||||
|
// 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 Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user