I have a mvc application. And I am using a API for retrieving. teachers.
This is the class:
[Authorize(Roles = IdentityRoles.Teacher)]
[RoutePrefix("api//current")]
public sealed class CurrentTeacherController : ApiControllerBase
{
private readonly ICurrentTeacherProcess _currentTeacherProcess;
/// <summary>
/// Constructor.
/// </summary>
public CurrentTeacherController(ICurrentTeacherProcess process)
{
_currentTeacherProcess = process;
}
/// <summary>
/// Gets the teacher data of the current user
/// </summary>
/// <returns>The TeacherDto of the current teacher</returns>
[Route("")]
[HttpGet]
public TeacherDto GetTeacher()
{
return _currentTeacherProcess.GetTeacher();
}
}
And I am using Postman for retriving a teacher. For example teacher with id: 1001.
And In Postman I put this:
http://localhost:6598/api/register/
But I get a : 404 not found exception.
This is the startup.cs file:
public sealed class Startup
{
/// <summary>
/// Configures the application for use with OWIN. This method is called implicitly by Microsoft.Owin.Host.SystemWeb.
/// </summary>
/// <param name="app"><see cref="IAppBuilder" />implementation.</param>
public void Configuration(IAppBuilder app)
{
var config = GlobalConfiguration.Configuration;
WebApiConfig.Register(config);
var container = AutofacConfig.Register(config);
app.UseAutofacLifetimeScopeInjector(container);
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
AuthenticationType = "Hallo",
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = ApiGatewaySecurityTokenHandler.CreateTokenValidationParameters(
"hoi", "hoi", IdentityRoles.Duo, IdentityRoles.Competent, IdentityRoles.Berichtenbox),
TokenHandler = container.Resolve<JwtSecurityTokenHandler>()
});
app.UseStageMarker(PipelineStage.PostAuthenticate);
app.UseMiddlewareFromContainer<ApiGatewayMiddleware>();
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
update with startup.cs file
You get a 404 because a handler doesn't exist in your API for that request. You need to add the id to your API route like so
[Route("{id}")]
[HttpGet]
public TeacherDto GetTeacher(int id/* or other type if you aren't using int as your primary key*/ )
{
return _currentTeacherProcess.GetTeacher(id);
}
And your request should be:
http://localhost:6598/api/register/teachers/current/1001
Related
My team and I created a custom OAuth to be used for external SSO. It works on localhost but as soon as we take it up to our staging environment we get an "The oauth state was missing or invalid." error.
We used "https://auth0.com/" for testing.
To try and troubleshoot this we overrode the following built in methods and via breakpoints can see that Query state comes back null.
protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri);
protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync();
I need some help figuring out why this is a problem on staging and not on local as we are a bit stumped. A theory we have is that the decoder used inside these methods change on var properties = Options.StateDataFormat.Unprotect(state); and thus because they aren't the same they can't decode each others states. I will put our implementation below, if its required I can paste the built in methods as well but I can't fathom the problem lying with the built in functions.
Startup:
foreach (var customAuthItem in customAuthList)
{
services.AddAuthentication().AddCustom(customAuthItem.CampaignId, options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.AuthorizationEndpoint = customAuthItem.AuthEndpoint;
options.TokenEndpoint = customAuthItem.TokenEndpoint;
options.UserInformationEndpoint = customAuthItem.UserInfoEndpoint;
options.ClientId = customAuthItem.ClientId;
options.ClientSecret = customAuthItem.ClientSecret;
});
}
Options:
public class CustomAuthenticationOptions : OAuthOptions
{
/// <summary>
/// Initializes a new instance of the <see cref="CustomAuthenticationOptions"/> class.
/// </summary>
public CustomAuthenticationOptions()
{
ClaimsIssuer = CustomAuthenticationDefaults.Issuer;
CallbackPath = CustomAuthenticationDefaults.CallbackPath;
AuthorizationEndpoint = CustomAuthenticationDefaults.AuthorizationEndpoint;
TokenEndpoint = CustomAuthenticationDefaults.TokenEndpoint;
UserInformationEndpoint = CustomAuthenticationDefaults.UserInformationEndpoint;
Scope.Add("openid");
Scope.Add("profile");
Scope.Add("email");
ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub");
}
/// Gets the list of fields to retrieve from the user information endpoint.
/// </summary>
public ISet<string> Fields { get; } = new HashSet<string>
{
"email",
"name",
"sub"
};
Defaults:
public static class CustomAuthenticationDefaults
{
/// <summary>
/// Default value for <see cref="AuthenticationScheme.Name"/>.
/// </summary>
public const string AuthenticationScheme = "Custom";
/// <summary>
/// Default value for <see cref="AuthenticationScheme.DisplayName"/>.
/// </summary>
public static readonly string DisplayName = "Custom";
/// <summary>
/// Default value for <see cref="AuthenticationSchemeOptions.ClaimsIssuer"/>.
/// </summary>
public static readonly string Issuer = "Custom";
/// <summary>
/// Default value for <see cref="RemoteAuthenticationOptions.CallbackPath"/>.
/// </summary>
public static readonly string CallbackPath = "/signin-custom";
/// <summary>
/// Default value for <see cref="OAuthOptions.AuthorizationEndpoint"/>.
/// </summary>
public static readonly string AuthorizationEndpoint = "https://dev-egd511ku.us.auth0.com/authorize";
/// <summary>
/// Default value for <see cref="OAuthOptions.TokenEndpoint"/>.
/// </summary>
public static readonly string TokenEndpoint = "https://dev-egd511ku.us.auth0.com/oauth/token";
/// <summary>
/// Default value for <see cref="OAuthOptions.UserInformationEndpoint"/>.
/// </summary>
public static readonly string UserInformationEndpoint = "https://dev-egd511ku.us.auth0.com/userinfo";
}
Handler:
protected override async Task<AuthenticationTicket> CreateTicketAsync(
[NotNull] ClaimsIdentity identity,
[NotNull] AuthenticationProperties properties,
[NotNull] OAuthTokenResponse tokens)
{
Serilog.Log.Debug("CustomAuthenticationHandler.CreateTicketAsync: STARTED!");
string endpoint = Options.UserInformationEndpoint;
if (Options.Fields.Count > 0)
{
endpoint = QueryHelpers.AddQueryString(endpoint, "fields", string.Join(',', Options.Fields));
}
using var request = new HttpRequestMessage(HttpMethod.Get, endpoint);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);
Serilog.Log.Debug("CustomAuthenticationHandler.CreateTicketAsync: ABOUT TO SEND REQUEST!");
using var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);
if (!response.IsSuccessStatusCode)
{
Serilog.Log.Debug($"CustomAuthenticationHandler.CreateTicketAsync: FAILED REQUEST: {response.ReasonPhrase}");
await Log.UserProfileErrorAsync(Logger, response, Context.RequestAborted);
throw new HttpRequestException("An error occurred while retrieving the user profile from Custom.");
}
var payloadString = await response.Content.ReadAsStringAsync();
Serilog.Log.Debug($"CustomAuthenticationHandler.CreateTicketAsync: PAYLOAD: {payloadString}");
using var payload = JsonDocument.Parse(payloadString);// Context.RequestAborted));
var principal = new ClaimsPrincipal(identity);
var context = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
context.RunClaimActions();
await Events.CreatingTicket(context);
return new AuthenticationTicket(context.Principal!, context.Properties, Scheme.Name);
}
EDIT: The error is received after successful login and after being redirected back to our site. I can see through sentry breadcrumbs that the states are correct so it seems to be a decryption issue.
It turns out the problem is because I AddAuthentication() twice, it ignores the follow-up registration of the auth methods, resulting in only one OAuth working. This is a bit of a problem because we want to support multiple SSO options for our clients, but might need to figure out a different approach. I am just glad I finally know where the problem is.
I have created a web api project and run as a windows service.
I have added MEF to load a dll (LibOne.dll) and use it in the controller (ValueController). But unable to get the values in the imported interface.
I followed this link to implement this and added MefDependencyResolver in my web api project.
How to integrate MEF with ASP.NET MVC 4 and ASP.NET Web API
in the values controller the IMyClass is returning always null. How to resolve this?
Is there anything I am mising?
Here is my Web Api Controller
[Export(typeof(ValuesController))]
public class ValuesController : ApiController
{
[Import(typeof(IMyClass))]
private IMyClass Myclass { get; set; }
public String GetString(Int32 id)
{
return Myclass.GetValues();
}
}
SelfHosted Service to run the web api as windows service
protected override void OnStart(string[] args)
{
var config = new HttpSelfHostConfiguration("http://localhost:8080");
Thread.Sleep(10000);
MefConfig.RegisterMef(config);
config.Routes.MapHttpRoute(
name: "API",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
HttpSelfHostServer server = new HttpSelfHostServer(config);
server.OpenAsync().Wait();
}
MEF registration
public static void RegisterMef(HttpConfiguration config)
{
var assemblyCatalog = new AggregateCatalog();
assemblyCatalog.Catalogs.Add(new DirectoryCatalog(#""));
var container = new CompositionContainer(assemblyCatalog);
var resolver = new MefDependencyResolver(container);
config.DependencyResolver = resolver;
}
Exporting this class from LibOne.dll
[Export(typeof(IMyClass))]
public class Super :IMyClass
{
public string GetValues()
{
return "My value";
}
}
MEFDependencyResolver:
internal class MefDependencyResolver : IDependencyResolver
{
private readonly CompositionContainer _container;
/// <summary />
/// <param name="container"></param>
public MefDependencyResolver(CompositionContainer container)
{
_container = container;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public IDependencyScope BeginScope()
{
return this;
}
/// <summary>
/// Called to request a service implementation.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementation or null.</returns>
public object GetService(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var name = AttributedModelServices.GetContractName(serviceType);
var export = _container.GetExportedValueOrDefault<object>(name);
return export;
}
/// <summary>
/// Called to request service implementations.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementations.</returns>
public IEnumerable<object> GetServices(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var exports = _container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
return exports;
}
/// <summary>
///
/// </summary>
public void Dispose()
{
}
}
I am currently having an API endpoint, which using EF fetches data from the database as such:
Controller:
/// <summary>
/// The View Controller Class
/// </summary>
[ApiController]
[Authorize]
[Route(ApiEndpointConfiguration.External)]
public class ViewController : ControllerBase
{
private readonly IViewService viewService;
private readonly ILogger logger;
private readonly IUserContext userContext;
/// <summary>
/// Constructs ViewController
/// </summary>
/// <param name="viewService">IViewService</param>
/// <param name="userContext">IUserContext</param>
/// <param name="loggerFactory">ILoggerFactory</param>
/// <param name="options">LoggerOptions</param>
public ViewController(
IViewService viewService,
IUserContext userContext,
ILoggerFactory loggerFactory,
LoggerOptions options)
{
this.userContext = userContext;
this.viewService = viewService;
logger = loggerFactory.CreateSystemLogger<ViewController>("Log", options);
}
/// <summary>
/// Retrieve TableViews you can view
/// OData is enabled to allow for building queries
/// </summary>
/// <returns>TableView</returns>
/// <response code="200">TableView</response>
/// <response code="401">Unauthorized</response>
/// <response code="403">Forbidden</response>
/// <response code="404">Not Found</response>
/// <response code="500">Internal Server Error</response>
[HttpGet]
[EnableQuery()]
public ActionResult Get()
{
logger.Information($"A GET request was performed by {HttpContext.Connection.Id}");
var userIdParameter = HttpContext.Request.Query["userId"];
Guid userId = string.IsNullOrEmpty(userIdParameter) ? userContext.UserId : Guid.Parse(userIdParameter);
bool isAllowed = userContext.CanExecute("AdminView");
if (!isAllowed && userContext.UserId != userId)
{
throw new InvalidPermissionsException(userContext.UserId,
"User does not have permission to get the view");
}
var views = viewService
.Get()
.Where(x => x.UserId == userId || x.UserId == null)
.ToList();
return Ok(views.ToViewModel());
}
I am able to filter the result using url as
https://localhost:5001/external/api/View?$filter=targetSystem%20eq%20%27frontpage%27%20and%20targetName%20eq%20%27car%27
But when I add count I don't see the count value anywhere?
why?
https://localhost:5001/external/api/View?$filter=targetSystem%20eq%20%27frontpage%27%20and%20targetName%20eq%20%27car%27&$count=true
in my startup.cs I have configured it as such
app.UseMvc(routeBuilder =>
{
routeBuilder.EnableDependencyInjection();
routeBuilder.Expand().Select().Count().OrderBy().Filter();
});
so count should be included? why is it not being parsed in my output?
I am interested in knowing the sql generated by odata when count is being queried, but it seems like count does not respond at all..
This is a sample OData request and response using count:
Request
https://localhost:5000/api/v1/HomepageBanner?%24filter=id%20eq%202&%24count=true
Response body
{
"#odata.context": "https://localhost:5000/api/v1/$metadata#HomepageBanner",
"#odata.count": 0,
"value": []
}
As you can see from the response, the one you are looking at is "#odata.count"
Edit:
To be honest, I can't see why you could filter but can't get the count, you could do filter means that the OData endpoint was working.
Maybe you could compare your solution with what I'm doing on my github repo?
https://github.com/martinussuherman/odata-test
I'm thinking I must be missing something obvious, but im trying to create a new DesignAutomationClient object like follows:
private void runDAButton_Click(object sender, EventArgs e)
{
createWorkItem();
}
private async Task createWorkItem()
{
var forgeConfig = new Autodesk.Forge.Core.ForgeConfiguration();
forgeConfig.ClientId = clientID;
forgeConfig.ClientSecret = clientSecret;
var apiInstance = new DesignAutomationClient();
// Code to create work item will go here
}
but when I do, the following error appears in my Visual Studio Debug/Immediate window after trying to execute the var apiInstance = new DesignAutomationClient(); line:
Exception thrown: 'System.TypeLoadException' in mscorlib.dll
Am i missing something obvious? The design automation client was downloaded using NuGet so i should have all the required depencies, but searches of forums for this kind of error all say it means I'm either missing a DLL file, or the type I'm looking for doesn't exist within a DLL, neither of which I believe are true.
This code is in a simple windows form application written in C#
There are no web servers or ASP.NET involved.
The user clicks a button on the form which runs the runDAButton_Click function(which in turn runs the createWorkItem() function). That function should create an instance of the API, and then use it to create my work item.
Can anyone help?
We need more information to troubleshoot, is it a ASP .NET core? how you are handling DI
but if your app is .NET core console app from the code as it appears.
The right way to do is.
dotnet new console
dotnet add package Autodesk.Forge.DesignAutomation --version 3.0.3
Code:
namespace daconsole
{
using Autodesk.Forge.Core;
using Autodesk.Forge.DesignAutomation;
using Autodesk.Forge.DesignAutomation.Model;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Defines the <see cref="ConsoleHost" />.
/// </summary>
class ConsoleHost : IHostedService
{
/// <summary>
/// The StartAsync.
/// </summary>
/// <param name="cancellationToken">The cancellationToken<see cref="CancellationToken"/>.</param>
/// <returns>The <see cref="Task"/>.</returns>
public Task StartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
/// <summary>
/// The StopAsync.
/// </summary>
/// <param name="cancellationToken">The cancellationToken<see cref="CancellationToken"/>.</param>
/// <returns>The <see cref="Task"/>.</returns>
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
/// <summary>
/// Defines the <see cref="App" />.
/// </summary>
internal class App
{
/// <summary>
/// Defines the api.
/// </summary>
public DesignAutomationClient api;
/// <summary>
/// Defines the config.
/// </summary>
public ForgeConfiguration config;
/// <summary>
/// Initializes a new instance of the <see cref="App"/> class.
/// </summary>
/// <param name="api">The api<see cref="DesignAutomationClient"/>.</param>
/// <param name="config">The config<see cref="IOptions{ForgeConfiguration}"/>.</param>
public App(DesignAutomationClient api, IOptions<ForgeConfiguration> config)
{
this.api = api;
this.config = config.Value;
}
/// <summary>
/// The CreateWorkItem.
/// </summary>
/// <returns>The <see cref="Task"/>.</returns>
private async Task CreateWorkItem()
{
//step1:
var forgeEnginesApi = api.EnginesApi;
ApiResponse<Page<string>> engines = await forgeEnginesApi.GetEnginesAsync();
if (engines.HttpResponse.IsSuccessStatusCode)
{
Console.WriteLine(JsonConvert.SerializeObject(engines.Content, Formatting.Indented));
}
//step2:
Console.WriteLine("\nActiviy Start");
var activitiesApi = api.ActivitiesApi;
ApiResponse<Page<string>> activitiesResp = await activitiesApi.GetActivitiesAsync();
List<string> listOfActivities = new List<string>();
string activityName = null;
if (activitiesResp.HttpResponse.IsSuccessStatusCode)
{
var page = activitiesResp.Content.PaginationToken;
activitiesResp.Content.Data.ForEach(e => listOfActivities.Add(e));
while (page != null)
{
activitiesResp = await activitiesApi.GetActivitiesAsync(page);
page = activitiesResp.Content.PaginationToken;
activitiesResp.Content.Data.ForEach(e => listOfActivities.Add(e));
}
var activities = listOfActivities.Where(a => a.Contains("PlotToPDF")).Select(a => a);
if (activities.Count() > 0)
{
activityName = activities.FirstOrDefault();
}
}
//step3:
Console.WriteLine("\nWorkItem Start...");
var workItemsApi = api.WorkItemsApi;
ApiResponse<WorkItemStatus> workItemStatus = await workItemsApi.CreateWorkItemAsync(new Autodesk.Forge.DesignAutomation.Model.WorkItem()
{
ActivityId = activityName,
Arguments = new Dictionary<string, IArgument>() {
{
"HostDwg",
new XrefTreeArgument() {
Url = "http://download.autodesk.com/us/samplefiles/acad/blocks_and_tables_-_metric.dwg",
Verb = Verb.Get
}
}, {
"Result",
new XrefTreeArgument() {
Verb = Verb.Put, Url = "azure blob storage url",
Headers = new Dictionary<string,string>()
{
{ "Content-Type","application/octet-stream" },
{ "x-ms-blob-type","BlockBlob" }
}
}
}
}
});
Console.Write("\tPolling status");
while (!workItemStatus.Content.Status.IsDone())
{
await Task.Delay(TimeSpan.FromSeconds(2));
workItemStatus = await workItemsApi.GetWorkitemStatusAsync(workItemStatus.Content.Id);
Console.Write(".");
}
Console.WriteLine(JsonConvert.SerializeObject(workItemStatus.Content, Formatting.Indented));
}
/// <summary>
/// The RunAsync.
/// </summary>
/// <returns>The <see cref="Task"/>.</returns>
public async Task RunAsync()
{
await CreateWorkItem();
}
}
/// <summary>
/// Defines the <see cref="Program" />.
/// </summary>
internal class Program
{
/// <summary>
/// The Main.
/// </summary>
/// <param name="args">The args<see cref="string[]"/>.</param>
/// <returns>The <see cref="Task"/>.</returns>
static async Task Main(string[] args)
{
var host = new HostBuilder()
.ConfigureAppConfiguration(builder =>
{
builder.AddEnvironmentVariables();
builder.AddForgeAlternativeEnvironmentVariables();
}).ConfigureServices((hostContext, services) =>
{ // add our no-op host (required by the HostBuilder)
services.AddHostedService<ConsoleHost>();
// our own app where all the real stuff happens
services.AddSingleton<App>();
// add and configure DESIGN AUTOMATION
services.AddDesignAutomation(hostContext.Configuration);
services.AddOptions();
})
.UseConsoleLifetime()
.Build();
using (host)
{
await host.StartAsync();
// Get a reference to our App and run it
var app = host.Services.GetRequiredService<App>();
await app.RunAsync();
await host.StopAsync();
}
}
}
}
add Forge Env to your launchSettings.json
{
"profiles": {
"daconsole": {
"commandName": "Project",
"environmentVariables": {
"FORGE_CLIENT_SECRET": "",
"FORGE_CLIENT_ID": ""
}
}
}
}
To run:
dotnet run --launch-profile daconsole
Yesterday I coded myself a simple RESTful web API in .NET Core (solution named Vault) with a single method that gets the profile of the user depending only on the Windows user name. I now have a second solution that will call some requests to my self-hosting service previously mentioned. When I use Postman, I can retrieve the data with ease when I call a GET on my only method in Vault, but when I build the URI in Mainframe and execute, I get an Unauthorized error and it confuses me as Vault does not require specific login like username and password. I also put a breakpoint in Vault and unlike when I'm using Postman, it does not reach my code when calling via the Mainframe solution.
Here where is build my REST request and call the service (GetProfile())
public VaultApiClient(ConfigurationManagerWrap configuration)
{
this.configuration = configuration;
this.client = new RestClient(new Uri(this.configuration.GetAppSetting<string>(ConfigurationKeys.VaultApiURL)));
}
/// <summary>
/// The get profile.
/// </summary>
/// <returns>
/// The <see cref="UserProfile"/>.
/// </returns>
public UserProfile GetProfile()
{
var request = new RestRequest("profile") { Method = Method.GET};
//request.AddParameter("profile", ParameterType.UrlSegment);
var response = this.client.Execute(request);
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception(
$"Could not get the user profile ({response.StatusCode} {response.StatusDescription})");
}
return RestJsonSerializer.Default.Deserialize<UserProfile>(response);
}
Im hosting local so the base URI, aka ConfigurationKeys.VaultApiURL, is localhost5000/api/
My Mainframe controller :
public HomeController()
: this(new VaultApiClient(new ConfigurationManagerWrap()))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HomeController"/> class.
/// </summary>
/// <param name="vaultApiClient">
/// The vault api client.
/// </param>
public HomeController(IVaultApiClient vaultApiClient)
{
this.vaultApiClient = vaultApiClient;
}
/// <summary>
/// The index.
/// </summary>
/// <returns>
/// The <see cref="ActionResult"/>.
/// </returns>
public ActionResult Index()
{
var profile = this.GetProfile();
this.ViewBag.IsEdit = false;
this.ViewBag.IsError = false;
this.ViewBag.ErrorMessage = "";
if (this.TempData.ContainsKey("IsEdit"))
{
this.ViewBag.IsEdit = true;
this.TempData.Remove("IsEdit");
if (this.TempData.ContainsKey("ErrorMessage"))
{
this.ViewBag.IsError = true;
this.ViewBag.ErrorMessage = this.TempData["ErrorMessage"];
this.TempData.Remove("ErrorMessage");
}
}
return this.View("Index", profile);
}
private UserProfile GetProfile()
{
return this.vaultApiClient.GetProfile();
}
And here is the vault controller method that handles the GET request in question:
[HttpGet]
[Route("/api/Profile")]
[Produces(typeof(UserProfile))]
public IActionResult SearchProfile()
{
try
{
if (!this.currentuser.IsAuthenticated)
{
throw new Exception("This service does not support anonymous calls.");
}
var profile = Task.Run(() => this.personalizationService.GetUserProfileAsync(this.currentuser.GetCurrentWindowsIdentityName)).Result;
var userProfile = this.persistenceToDataModelConverter.Convert(profile);
userProfile.UserAdLogin = this.currentuser.GetCurrentWindowsIdentityName;
return this.Ok(userProfile);
}
catch (Exception ex)
{
return this.NotFound(ex);
}
}
Lastly, here are a few pics of before and when the error is thrown.
Credential information must be provided with client request in order to authenticate with the server.