TypeLoadException when trying to UnitTest Azure Function with Microsoft.Identity.Web - unit-testing

The bounty expires in 22 hours. Answers to this question are eligible for a +50 reputation bounty.
Pat Long - Munkii Yebee is looking for an answer from a reputable source.
I am trying to UnitTest an Azure Function that reads a parameter directly from the querystring
[FunctionName("GetEntityId")]
public async Task<IActionResult> GetEntityId(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "entityid")] HttpRequest req)
{
if (!int.TryParse(req.Query["quantity"], out int quantity))
{
quantity = 1;
}
quantity = Math.Min(quantity, 100);
var entityIds = await this.entityIdGenerator.NewEntityIdAsync(userId, quantity);
if (entityIds is null)
{
return new System.Web.Http.InternalServerErrorResult();
}
else
{
return new OkObjectResult(entityIds);
}
}
There are unit tests that have mocked the HttpRequest and HttpContext
var reqMock = new Mock<HttpRequest>();
var httpContextMock = new Mock<HttpContext>();
var responseMock = new Mock<HttpResponse>();
responseMock.Setup(res => res.Headers).Returns(new HeaderDictionary());
httpContextMock.Setup(http => http.Response).Returns(responseMock.Object);
httpContextMock.Setup(http => http.Request).Returns(reqMock.Object);
The mock for the querystring uses QueryCollection
reqMock.Setup(req => req.Query).Returns(new QueryCollection(queryString));
Up until recently this worked fine but since I introduced Microsoft.Identity.Web to the Azure Function I get the following error. If I remove the package reference the Unit Test passes
System.TypeLoadException: 'Could not load type
'Microsoft.AspNetCore.Http.Internal.QueryCollection' from assembly
'Microsoft.AspNetCore.Http, Version=3.1.31.0, Culture=neutral,
PublicKeyToken=adb9793829ddae60'.'
I realise that using a class inside an Internal MS library looks wrong but this is one of the main ways to mock the HttpRequest and was working
If I try and used DefaultHttpRequest and DefaultHttpContext I get a different error but for a similar reason
Could not load type
'Microsoft.AspNetCore.Http.Internal.DefaultHttpRequest' from assembly
'Microsoft.AspNetCore.Http, Version=3.1.31.0, Culture=neutral,
PublicKeyToken=adb9793829ddae60'.'
Something in the Microsoft.Identity library is causing a different dependent library to be called from what I can tell. I have tried updating Microsoft.Identity to latest but same error
The packages in the CSPROJ file are
<ItemGroup>
<PackageReference Include="AutoMapper" Version="11.0.1" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Avatar.Infrastructure.EfCore" Version="1.0.0-CI-20230130-181631" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.6.0" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Logging.ApplicationInsights" Version="3.0.30" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.28" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.28" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.49.1" />
<PackageReference Include="Microsoft.Identity.Web" Version="1.25.10" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.9" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="6.26.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.25.1" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.13" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<AdditionalFiles Include="stylecop.json" />
</ItemGroup>
The full UnitTest code is
[TestCategory("AvatarFunctionAppTest Story 893")]
[TestMethod]
public async Task GetEntityIdNotAuthorised()
{
HttpRequest mockedRequest = this.HttpRequestSetup();
var result = await new AvatarFunctionApp(
this.EasyAuthProxy,
this.EntityIdGenerator,
this.TableStorage,
this.mockSignalService.Object,
this.log.Object)
.GetEntityId(mockedRequest);
Assert.IsTrue(result is UnauthorizedResult);
}
public HttpRequest HttpRequestSetup(IHeaderDictionary headers = null)
{
return this.HttpRequestSetup(new Dictionary<string, StringValues>(), headers);
}
public HttpRequest HttpRequestSetup(Dictionary<string, StringValues> queryString, IHeaderDictionary headers = null, Uri uri = null)
{
var reqMock = new Mock<HttpRequest>();
var httpContextMock = new Mock<HttpContext>();
var responseMock = new Mock<HttpResponse>();
responseMock.Setup(res => res.Headers).Returns(new HeaderDictionary());
httpContextMock.Setup(http => http.Response).Returns(responseMock.Object);
httpContextMock.Setup(http => http.Request).Returns(reqMock.Object);
reqMock.Setup(req => req.Query).Returns(new QueryCollection(queryString));
reqMock.Setup(req => req.Body).Returns(default(Stream));
reqMock.Setup(req => req.Headers).Returns(headers ?? new HeaderDictionary());
reqMock.Setup(req => req.HttpContext).Returns(httpContextMock.Object);
if (uri is Uri)
{
reqMock.Setup(req => req.Scheme).Returns(uri.Scheme);
reqMock.Setup(req => req.Host).Returns(new HostString(uri.Host, uri.Port));
reqMock.Setup(req => req.Path).Returns(uri.AbsolutePath);
}
this.mockHttpContextAccessor.Setup(hca => hca.HttpContext).Returns(httpContextMock.Object);
return reqMock.Object;
}

Related

System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary: DYNAMICS 365 Plugin

When I run a Unit Test for my plugin I get the following Exception being Thrown:
Message: Test method Plugins.Tests.UnitTest1.TestUnitPlugin threw exception:
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
The following link will give you the stack trace:
Stacktrace
Even when I deploy & register my plugin to the online instance, I would get the same message!!
My Plugin code looks like this:
using System;
using System.Collections.Generic;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
/// <summary>
/// This plugin takes the data provided in the contract lines and makes Unit Orders.. Inside the unit orders, an Alter Unit Orders table is present.
/// The Alter Unit Orders table describes the daily order for each day in the contract's duration.
/// </summary>
namespace DCWIMS.Plugins
{
[CrmPluginRegistration(MessageNameEnum.Update,
"contract",
StageEnum.PreOperation,
ExecutionModeEnum.Synchronous,
"title",
"Post-Update Contract",
1000,
IsolationModeEnum.Sandbox,
Image1Name = "PreImage",
Image1Type = ImageTypeEnum.PreImage,
Image1Attributes = "title")]
public class UnitPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// Extract the tracing service for use in debugging sandboxed plug-ins.
// Wil be registering this plugin, thus will need to add tracing service related code.
ITracingService tracing = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
//obtain execution context from service provider.
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));
// The InputParameters colletion contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
//obtain the target entity from the input parameters.
Entity entity = (Entity)context.InputParameters["Target"];
//Obtain Target Entity Id
var targetId = entity.Id.ToString();
//verify that the target entity represents the the contract entity and is active
if (entity.LogicalName != "contract" && entity.GetAttributeValue<OptionSetValue>("statecode").Value != 0)
return;
//obtain the organization service for web service calls.
IOrganizationServiceFactory serviceFactory =
(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
//Get Contract StartDate
DateTime startDate = (DateTime)entity["activeon"];
//Get Contract EndDate
DateTime endDate = (DateTime)entity["expireson"];
//Get all weekdays in the contract duration
Eachday range = new Eachday();
var weekdays = range.WeekDay(startDate, endDate); //weekdays list
//Get Contract Number
string contractNumber = (string)entity["contractnumber"];
//Query and aggregate each Weekday's order for the 3 different meal times...
//AM SNACK
string unitsum_am = #" <fetch aggregate='true' distinct='false' >
<entity name='contract' >
<link-entity name='contractdetail' from = 'contractid' to = 'contractid' >
<attribute name='new_mondayunits' alias='new_mondayunits_amsum' aggregate='sum' />
<attribute name='new_tuesdayunits' alias='new_tuesdayunits_amsum' aggregate='sum' />
<attribute name='new_unitswednesday' alias='new_unitswednesday_amsum' aggregate='sum' />
<attribute name='new_unitsthursday' alias='new_unitsthursday_amsum' aggregate='sum' />
<attribute name='new_unitsfriday' alias='new_unitsfriday_amsum' aggregate='sum' />
<filter type='and' >
<condition value='100000001' attribute='new_servingtime' operator= 'eq' />
<condition value='0' attribute='statecode' operator= 'eq' />
<condition value='" + targetId + #"' attribute='contractid' operator= 'eq' />
</filter >
</link-entity>
</entity >
</fetch>";
EntityCollection unitsum_am_result =
service.RetrieveMultiple(new FetchExpression(unitsum_am));
var am_list = new List<int>();
foreach(var unit in unitsum_am_result.Entities)
{
var mondaysum = ((int)((AliasedValue)unit["new_mondayunits_amsum"]).Value);
am_list.Add(mondaysum);
var tuesdaysum = ((int)((AliasedValue)unit["new_tuesdayunits_amsum"]).Value);
am_list.Add(tuesdaysum);
var wednesdaysum= ((int)((AliasedValue)unit["new_unitswednesday_amsum"]).Value);
am_list.Add(wednesdaysum);
var thursdaysum= ((int)((AliasedValue)unit["new_unitsthursday_amsum"]).Value);
am_list.Add(thursdaysum);
var fridaysum= ((int)((AliasedValue)unit["new_unitsfriday_amsum"]).Value);
am_list.Add(fridaysum);
}
//LUNCH
string unitsum_lunch = #" <fetch aggregate='true' distinct='false' >
<entity name='contract' >
<link-entity name='contractdetail' from = 'contractid' to = 'contractid' >
<attribute name='new_mondayunits' alias='new_mondayunits_lunchsum' aggregate='sum' />
<attribute name='new_tuesdayunits' alias='new_tuesdayunits_lunchsum' aggregate='sum' />
<attribute name='new_unitswednesday' alias='new_unitswednesday_lunchsum' aggregate='sum' />
<attribute name='new_unitsthursday' alias='new_unitsthursday_lunchsum' aggregate='sum' />
<attribute name='new_unitsfriday' alias='new_unitsfriday_lunchsum' aggregate='sum' />
<filter type='and' >
<condition value='100000002' attribute='new_servingtime' operator= 'eq' />
<condition value='0' attribute='statecode' operator= 'eq' />
<condition value='" + targetId + #"' attribute='contractid' operator= 'eq' />
</filter >
</link-entity>
</entity >
</fetch>";
EntityCollection unitsum_lunch_result =
service.RetrieveMultiple(new FetchExpression(unitsum_lunch));
var lunch_list = new List<int>();
foreach (var unit in unitsum_lunch_result.Entities)
{
var mondaysum = ((int)((AliasedValue)unit["new_mondayunits_lunchsum"]).Value);
lunch_list.Add(mondaysum);
var tuesdaysum = ((int)((AliasedValue)unit["new_tuesdayunits_lunchsum"]).Value);
lunch_list.Add(tuesdaysum);
var wednesdaysum = ((int)((AliasedValue)unit["new_unitswednesday_lunchsum"]).Value);
lunch_list.Add(wednesdaysum);
var thursdaysum = ((int)((AliasedValue)unit["new_unitsthursday_lunchsum"]).Value);
lunch_list.Add(thursdaysum);
var fridaysum = ((int)((AliasedValue)unit["new_unitsfriday_lunchsum"]).Value);
lunch_list.Add(fridaysum);
}
//PM SNACK
string unitsum_pm = #" <fetch aggregate='true' distinct='false' >
<entity name='contract' >
<link-entity name='contractdetail' from = 'contractid' to = 'contractid' >
<attribute name='new_mondayunits' alias='new_mondayunits_pmsum' aggregate='sum' />
<attribute name='new_tuesdayunits' alias='new_tuesdayunits_pmsum' aggregate='sum' />
<attribute name='new_unitswednesday' alias='new_unitswednesday_pmsum' aggregate='sum' />
<attribute name='new_unitsthursday' alias='new_unitsthursday_pmsum' aggregate='sum' />
<attribute name='new_unitsfriday' alias='new_unitsfriday_pmsum' aggregate='sum' />
<filter type='and' >
<condition value='100000003' attribute='new_servingtime' operator= 'eq' />
<condition value='0' attribute='statecode' operator= 'eq' />
<condition value='" + targetId + #"' attribute='contractid' operator= 'eq' />
</filter >
</link-entity>
</entity >
</fetch>";
EntityCollection unitsum_pm_result =
service.RetrieveMultiple(new FetchExpression(unitsum_pm));
var pm_list = new List<int>();
foreach (var unit in unitsum_pm_result.Entities)
{
var mondaysum = ((int)((AliasedValue)unit["new_mondayunits_pmsum"]).Value);
pm_list.Add(mondaysum);
var tuesdaysum = ((int)((AliasedValue)unit["new_tuesdayunits_pmsum"]).Value);
pm_list.Add(tuesdaysum);
var wednesdaysum = ((int)((AliasedValue)unit["new_unitswednesday_pmsum"]).Value);
pm_list.Add(wednesdaysum);
var thursdaysum = ((int)((AliasedValue)unit["new_unitsthursday_pmsum"]).Value);
pm_list.Add(thursdaysum);
var fridaysum = ((int)((AliasedValue)unit["new_unitsfriday_pmsum"]).Value);
pm_list.Add(fridaysum);
}
foreach(var day in weekdays)
{
var alterunit = new Entity("new_alterunitorder");
alterunit.Attributes.Add("new_orderdate", DateTime.Parse(day));
switch (day.Split(',')[0])
{
case "Monday":
alterunit.Attributes.Add("new_amsnack", am_list[0]);
alterunit.Attributes.Add("new_lunch", lunch_list[0]);
alterunit.Attributes.Add("new_pmsnack", pm_list[0]);
break;
case "Tuesday":
alterunit.Attributes.Add("new_amsnack", am_list[1]);
alterunit.Attributes.Add("new_lunch", lunch_list[1]);
alterunit.Attributes.Add("new_pmsnack", pm_list[1]);
break;
case "Wednesday":
alterunit.Attributes.Add("new_amsnack", am_list[2]);
alterunit.Attributes.Add("new_lunch", lunch_list[2]);
alterunit.Attributes.Add("new_pmsnack", pm_list[2]);
break;
case "Thursday":
alterunit.Attributes.Add("new_amsnack", am_list[3]);
alterunit.Attributes.Add("new_lunch", lunch_list[3]);
alterunit.Attributes.Add("new_pmsnack", pm_list[3]);
break;
case "Friday":
alterunit.Attributes.Add("new_amsnack", am_list[4]);
alterunit.Attributes.Add("new_lunch", lunch_list[4]);
alterunit.Attributes.Add("new_pmsnack", pm_list[4]);
break;
default:
Console.WriteLine($"An unexpected value ({day.Split(',')})");
break;
}
alterunit.Attributes.Add("new_name", contractNumber); //set the record name
//set the unit order record relation
alterunit.Attributes["new_orderlineid"] =
new EntityReference("new_alterunitorder", unitOrderId);
service.Create(alterunit);
}
}
catch (FaultException<OrganizationServiceFault> ex)
{
throw new InvalidPluginExecutionException("An error occured.. Phil is responsible.", ex);
}
catch (Exception ex)
{
tracing.Trace("An Error Occured: {0}", ex.ToString());
throw;
}
}
}
}
}
Here is the code for Eachday:
using System;
using System.Collections.Generic;
namespace DCWIMS.Plugins
{
public class Eachday
{
public List<string> WeekDay(DateTime from, DateTime thru)
{
List<string> days_list = new List<string>();
for (var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
{
days_list.Add(day.ToLongDateString());
if (day.DayOfWeek == DayOfWeek.Sunday || day.DayOfWeek == DayOfWeek.Saturday)
days_list.Remove(day.ToLongDateString());
}
return days_list;
}
}
}
My unit test looks like this:
using DCWIMS.Plugins;
using Microsoft.Crm.Sdk.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Xrm.Sdk;
namespace Plugins.Tests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
[TestCategory("Unit Test")]
public void TestUnitPlugin()
{
using (var pipline = new PluginPipeline(FakeMessageNames.Update, FakeStages.PreOperation, new Entity("contract")))
{
var plugin = new UnitPlugin();
pipline.Execute(plugin);
}
}
}
}
Even when I registered the plugin on the actual CRM instance I got this error message:
Here is the log file retrieved from CRM Online!
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=8.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Unexpected exception from plug-in (Execute): DCWIMS.Plugins.UnitPlugin: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.Detail:
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
<ActivityId>4025e0f8-eed5-4b7f-a3b1-52a9f2a6f2cc</ActivityId>
<ErrorCode>-2147220956</ErrorCode>
<ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<Message>Unexpected exception from plug-in (Execute): DCWIMS.Plugins.UnitPlugin: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.</Message>
<Timestamp>2018-07-20T17:47:36.4061434Z</Timestamp>
<ExceptionRetriable>false</ExceptionRetriable>
<ExceptionSource i:nil="true" />
<InnerFault i:nil="true" />
<OriginalException i:nil="true" />
<TraceText>
[Plugins: DCWIMS.Plugins.UnitPlugin]
[dbb33fa1-448c-e811-815c-480fcff4b5b1: Pre-Create Contract]
An Error Occured: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Microsoft.Xrm.Sdk.AttributeCollection.get_Item(String attributeName)
at DCWIMS.Plugins.UnitPlugin.Execute(IServiceProvider serviceProvider)
</TraceText>
</OrganizationServiceFault
>
Unit testing ain't my forte. But I will try to guide you.
First, my opinion on unit testing. I don't value it much in Dynamics because it's an environment that is hard to control. You can test that your business logic is well implemented in the plugin but a javascript, a business rule, a workflow or an action can derail your logic. Your plugin can say blue but an async workflow change it to red right after.
Instead, I prefer UI testing. It will test the process from A to Z and force the execution of all the components mentioned above. Here's a nice framework I recommend: https://github.com/Microsoft/EasyRepro
That being said. To solve your problem you also need to mock the Organization Service and return fake data. By that, I mean this line:
EntityCollection unitsum_am_result = service.RetrieveMultiple(new FetchExpression(unitsum_am));
Sadly, even if you mock, you can't really parse the fetchXml and validate it.
Then, after returning the fake data you should assert that this line, create an entity with the right sums:
service.Create(alterunit);

Sharepoint 2013 FBA Error:Could not retrieve the IIS Settings.Parameter name: context

(The original post is here:https://social.technet.microsoft.com/Forums/sharepoint/en-US/6b02dfe8-5594-4d25-991a-51ac9a0528b7/sharepoint-2013-fba-errorcould-not-retrieve-the-iis-settingsparameter-name-context?forum=sharepointadminprevious)
I am trying to use windows live to login sharepoint 2013. From some posts, I could get windows live token(aouth 2.0) and windows live user profile. It will redirect to my sharepoint site.
I follow some articles to develop my custom login page:
also I defined my membership provider and role provider
public class LiveMembershipProvider : MembershipProvider
{
private MembershipUserCollection employees;
private void generateUsers()
{
//Mock Data
employees = new MembershipUserCollection();
employees.Add(new MembershipUser(this.Name, "Jack Chen", "JackChen", "Jack#Chen.com", "What your Name?", "I am Jack", true, false, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today));
employees.Add(new MembershipUser(this.Name, "Bruce Li", "BruceLi", "BruceLi#Li.com", "How are u?", "How old are u", true, false, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today));
employees.Add(new MembershipUser(this.Name, "Eyes Wang", "EyesWang", "EyesWang#Mintcode.com", "What the hell?", "what the fuck", true, false, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today));
}
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
{
if (employees == null) generateUsers();
MembershipUserCollection returnFoundUsers = new MembershipUserCollection();
(employees.Cast<MembershipUser>().
Where(membershipUser => membershipUser.UserName.ToLowerInvariant().Contains(usernameToMatch.ToLowerInvariant())))
.ToList().ForEach(returnFoundUsers.Add);
totalRecords = returnFoundUsers.Count;
return returnFoundUsers;
}
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
{
if (employees == null) generateUsers();
totalRecords = employees.Count;
return employees;
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
if (employees == null) generateUsers();
IEnumerable<MembershipUser> usersFound = employees.Cast<MembershipUser>().Where(membershipUser => membershipUser.UserName == username);
return usersFound.FirstOrDefault();
}
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
if (employees == null) generateUsers();
IEnumerable<MembershipUser> usersFound = employees.Cast<MembershipUser>().Where(membershipUser => membershipUser.ProviderUserKey.ToString() == providerUserKey.ToString());
return usersFound.FirstOrDefault();
}
public override string GetUserNameByEmail(string email)
{
if (employees == null) generateUsers();
IEnumerable<MembershipUser> usersFound = employees.Cast<MembershipUser>().Where(membershipUser => membershipUser.Email.ToLowerInvariant() == email.ToLowerInvariant());
MembershipUser user = usersFound.FirstOrDefault();
if (user != null)
return user.UserName;
else
return null;
}
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
if (employees == null) generateUsers();
MembershipUserCollection returnFoundUsers = new MembershipUserCollection();
(employees.Cast<MembershipUser>().
Where(membershipUser => membershipUser.Email.ToLowerInvariant().Contains(emailToMatch.ToLowerInvariant())))
.ToList().ForEach(returnFoundUsers.Add);
totalRecords = returnFoundUsers.Count;
return returnFoundUsers;
}
public override bool ValidateUser(string username, string password)
{
//return true;
if (employees == null) generateUsers();
IEnumerable<MembershipUser> usersFound = employees.Cast<MembershipUser>().Where(membershipUser => membershipUser.UserName == username);
MembershipUser user = usersFound.FirstOrDefault();
if (user != null)
{
if (string.IsNullOrEmpty(password))
{
return false;
}
else
{
return true;
}
}
else
return false;
}
}
public class LiveRoleProvider : RoleProvider
{
public override string ApplicationName { get; set; }
private string[] m_AllRoles = { "Vendor" };
private string[,] m_RolesForUser = new string[,] {
{"Eyes Wang", "Vendor"},
{"Bruce Li","Vendor"},
{"Jack Chen","Vendor"}
};
public override string[] GetAllRoles()
{
return m_AllRoles;
}
public override string[] GetRolesForUser(string username)
{
List<string> roles = new List<string>();
for (int i = 0; i <= m_RolesForUser.GetUpperBound(0); i++)
{
if (m_RolesForUser[i, 0] == username)
{
roles = m_RolesForUser[i, 1].Split(',').ToList<string>();
}
}
return roles.ToArray();
}
public override string[] GetUsersInRole(string rolename)
{
List<string> users = new List<string>();
for (int i = 0; i <= m_RolesForUser.GetUpperBound(0); i++)
{
List<string> userRoles = m_RolesForUser[i, 1].Split(',').ToList<string>();
if (userRoles.Where(userRole => userRole == rolename).Count() > 0)
{
users.Add(m_RolesForUser[i, 0]);
}
}
return users.ToArray();
}
public override bool IsUserInRole(string username, string rolename)
{
List<string> usersForRole = GetUsersInRole(rolename).ToList();
if (usersForRole.Where(userName => userName == username).Count() > 0)
{
return true;
}
else
{
return false;
}
}
public override bool RoleExists(string rolename)
{
bool roleExsists = m_AllRoles.ToList().Where(roleName => roleName == rolename).Count() > 0;
return roleExsists;
}
public override string[] FindUsersInRole(string rolename, string usernameToMatch)
{
List<string> users = GetUsersInRole(rolename).ToList<string>();
List<string> foundUsers = users.Where(userName => userName.ToLowerInvariant().Contains(usernameToMatch.ToLowerInvariant())).ToList<string>();
return foundUsers.ToArray();
}
}
In the Central Application web.config
I add
<roleManager>
<providers>
<add name="LiveRoleProvider" type="SPLiveWebForm.LiveRoleProvider,SPLiveWebForm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34a64026791bbfa4" />
</providers>
</roleManager>
<membership>
<providers>
<add name="LiveMembershipProvider" type="SPLiveWebForm.LiveMembershipProvider,SPLiveWebForm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34a64026791bbfa4" />
</providers>
</membership>
<PeoplePickerWildcards>
<clear />
<add key="AspNetSqlMembershipProvider" value="%" />
<add key="LiveMembershipProvider" value="%" />
</PeoplePickerWildcards>
In the WA web.config
<membership defaultProvider="i">
<providers>
<add name="i" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="LiveMembershipProvider" type="SPLiveWebForm.LiveMembershipProvider,SPLiveWebForm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34a64026791bbfa4" />
</providers>
</membership>
<roleManager defaultProvider="c" enabled="true" cacheRolesInCookie="false">
<providers>
<add name="c" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="LiveRoleProvider" type="SPLiveWebForm.LiveRoleProvider,SPLiveWebForm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34a64026791bbfa4" />
</providers>
</roleManager>
<PeoplePickerWildcards>
<clear />
<add key="AspNetSqlMembershipProvider" value="%" />
<add key="LiveMembershipProvider" value="%" />
</PeoplePickerWildcards>
In the STS web.config
<system.web>
<membership defaultProvider="i">
<providers>
<add name="i" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="LiveMembershipProvider" type="SPLiveWebForm.LiveMembershipProvider,SPLiveWebForm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34a64026791bbfa4" />
</providers>
</membership>
<roleManager defaultProvider="c" enabled="true" cacheRolesInCookie="false">
<providers>
<add name="c" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<add name="LiveRoleProvider" type="SPLiveWebForm.LiveRoleProvider,SPLiveWebForm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34a64026791bbfa4" />
</providers>
</roleManager>
</system.web>
I could successfully login to share point by using the default login page (http://www.akmii.com/_forms/default.aspx)
But using my customize page (when I get windows live user profile then try to use the follow method to login sharepoint)
private void SPUserLogin(string usrName)
{
string userProviderName = string.Empty;
string roleProviderName = string.Empty;
foreach (MembershipProvider p in Membership.Providers)
{
if (p.GetType().Equals(typeof(LiveMembershipProvider)))
{
userProviderName = p.Name;
break;
}
}
foreach (RoleProvider rp in System.Web.Security.Roles.Providers)
{
if (rp.GetType().Equals(typeof(LiveRoleProvider)))
{
roleProviderName = rp.Name;
break;
}
}
SecurityToken tk = null;
try
{
tk = SPSecurityContext.SecurityTokenForFormsAuthentication(
new Uri(SPContext.Current.Web.Url), userProviderName, roleProviderName,
"Jack Chen", "123", SPFormsAuthenticationOption.PersistentSignInRequest);
}
catch (Exception e)
{
Response.Write(e.Message);
}
if (tk != null)
{
//try setting the authentication cookie
SPFederationAuthenticationModule fam = SPFederationAuthenticationModule.Current;
fam.SetPrincipalAndWriteSessionToken(tk);
//look for the Source query string parameter and use that as the redirection
//string src = Request.QueryString["Source"];
string src = "http://www.akmii.com/_layouts/15/start.aspx#/SitePages/Home.aspx";
if (!string.IsNullOrEmpty(src))
Response.Redirect(src);
}
else
{
}
}
}
There is an exception throwing out in the catch section:
Could not retrieve the IIS Settings.Parameter name: context
The error stack as follows:
at Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannel.ReadResponse(Message response)
at Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannel.Issue(RequestSecurityToken rst, RequestSecurityTokenResponse& rstr)
at Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannel.Issue(RequestSecurityToken rst)
at Microsoft.SharePoint.SPSecurityContext.SecurityTokenForContext(Uri context, Boolean bearerToken, SecurityToken onBehalfOf, SecurityToken actAs, SecurityToken delegateTo, SPRequestSecurityTokenProperties properties)
at Microsoft.SharePoint.SPSecurityContext.SecurityTokenForFormsAuthentication(Uri context, String membershipProviderName, String roleProviderName, String username, String password, SPFormsAuthenticationOption options)
at SPLiveWebForm.Layouts.SPLiveWebForm.Login.SPUserLogin(String usrName)
If I use
bool status = SPClaimsUtility.AuthenticateFormsUser(
new Uri(SPContext.Current.Web.Url),
usrName,
"123");
The same exception throw out.
at Microsoft.SharePoint.IdentityModel.SPFormsOriginalIssuerBuilder.GetFormsAuthenticationProviderFromContext(Uri context)
at Microsoft.SharePoint.IdentityModel.SPFormsOriginalIssuerBuilder.ValidateFormsAuthProviderNames(Uri context, String membershipProvider, String roleProvider)
at Microsoft.SharePoint.IdentityModel.SPFormsOriginalIssuerBuilder.SetProviderNames()
at Microsoft.SharePoint.IdentityModel.SPSecurityTokenService.SPRequestInfo.InitializeForForms(SPRequestSecurityToken request)
at Microsoft.SharePoint.IdentityModel.SPSecurityTokenService.GetTokenLifetime(Lifetime requestLifetime)
at Microsoft.IdentityModel.SecurityTokenService.SecurityTokenService.Issue(IClaimsPrincipal principal, RequestSecurityToken request)
at Microsoft.SharePoint.IdentityModel.SPSecurityTokenService.Issue(IClaimsPrincipal principal, RequestSecurityToken request)
at Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract.DispatchRequest(DispatchContext dispatchContext)
at Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract.ProcessCore(Message requestMessage, WSTrustRequestSerializer requestSerializer, WSTrustResponseSerializer responseSerializer, String requestAction, String responseAction, String trustNamespace)
at Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract.ProcessTrust13Issue(Message message)
at SyncInvokeProcessTrust13Issue(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
I spend whole day to dig this issue but failed.
Is there any solution to resolve this?
Many Thanks!
Vincent
I had the same problem.
In my case I had to go to the Central Administartion => System Settings => Configure alternate access mappings.
Click on "Edit Public URLs", select Your app in "Alternate access mappings collection" and then fill up "Internet" textbox.
I am not sure what value is correct, but I filled it with my sharepoint URL with default (80) port.
Hope it help You.

Google Glass Live Card not inserting

Glass GDK here. Trying to insert a livecard using remote views from service. I'm launching service via voice invocation. The voice command works, however it appears my service is not starting(no entries in log). Service is in android manifest. Below is code:
public class PatientLiveCardService extends Service {
private static final String LIVE_CARD_ID = "timer";
#Override
public void onCreate() {
Log.warn("oncreate");
super.onCreate();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
publishCard(this);
return START_STICKY;
}
#Override
public void onDestroy() {
unpublishCard(this);
super.onDestroy();
}
private void publishCard(Context context) {
Log.info("inserting live card");
if (mLiveCard == null) {
String cardId = "my_card";
TimelineManager tm = TimelineManager.from(context);
mLiveCard = tm.getLiveCard(cardId);
mLiveCard.setViews(new RemoteViews(context.getPackageName(),
R.layout.activity_vitals));
Intent intent = new Intent(context, MyActivity.class);
mLiveCard.setAction(PendingIntent
.getActivity(context, 0, intent, 0));
mLiveCard.publish();
} else {
// Card is already published.
return;
}
}
private void unpublishCard(Context context) {
if (mLiveCard != null) {
mLiveCard.unpublish();
mLiveCard = null;
}
}
}
Here is AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET" >
</uses-permission>
<uses-permission android:name="android.permission.RECORD_AUDIO" >
</uses-permission>
<application
android:name="com.myApp"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.myApp.MyActivity"
android:label="#string/app_name"
android:screenOrientation="landscape" >
</activity>
<service android:name="com.myApp.services.MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/voice_trigger_get_patient" />
</service>
</application>
This is a bug with XE11: the service is not started after the speech recognizer is complete.
As a workaround, you can have your voice trigger start an Activity which:
Processes the recognized speech in onResume.
Once the speech is processed, starts your Service with startService.
Calls finish to jump to the published LiveCard.

Why don't change lifecycle state of mule runtime?

I want to save some informaion to database when I send a request to mule service.
for this issue: I wrote below config in xml file:
<mule xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf" xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting"
xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:mule-ss="http://www.mulesoft.org/schema/mule/spring-security"
xmlns:ss="http://www.springframework.org/schema/security" xmlns:jdbc="http://www.mulesoft.org/schema/mule/jdbc"
xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.3.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/spring-security http://www.mulesoft.org/schema/mule/spring-security/3.3/mule-spring-security.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.mulesoft.org/schema/mule/jdbc http://www.mulesoft.org/schema/mule/jdbc/current/mule-jdbc.xsd ">
<spring:beans>
<spring:bean id="Initializer" name="Initializer" class="org.mule.example.scripting.IpClient" doc:name="Bean"/>
</spring:beans>
<notifications>
<notification event="COMPONENT-MESSAGE"/>
<notification-listener ref="Initializer"/>
</notifications>
<configuration doc:name="Configuration">
<expression-language>
<global-functions>
def parseIp(fullIp) {
return
fullIp.substring(fullIp.indexOf('/') + 1, fullIp.indexOf(':'))
}
</global-functions>
</expression-language>
</configuration>
<http:connector name="httpConnector" doc:name="HTTP\HTTPS">
<service-overrides sessionHandler="org.mule.session.NullSessionHandler" />
</http:connector>
<mule-ss:security-manager>
<mule-ss:delegate-security-provider
name="memory-dao" delegate-ref="authenticationManager" />
</mule-ss:security-manager>
<spring:beans>
<ss:authentication-manager alias="authenticationManager">
<ss:authentication-provider>
<ss:user-service id="userService">
<ss:user name="weather" password="weather" authorities="ROLE_ADMIN" />
</ss:user-service>
</ss:authentication-provider>
</ss:authentication-manager>
</spring:beans>
<flow name="Serive_test" doc:name="Serive_test">
<http:inbound-endpoint host="localhost" port="8089"
path="service/local-weather" exchange-pattern="request-response"
doc:name="HTTP">
<mule-ss:http-security-filter realm="mule-realm" />
</http:inbound-endpoint>
<async doc:name="Async">
<set-variable variableName="remoteClientAddress"
value="#[parseIp(message.inboundProperties['MULE_REMOTE_CLIENT_ADDRESS'])]"
doc:name="Variable" />
<message-properties-transformer
doc:name="myproperty" scope="session">
<add-message-property key="message.payload.remoteClientAddress"
value="#[parseIp(message.inboundProperties['MULE_REMOTE_CLIENT_ADDRESS'])]" />
</message-properties-transformer>
<component doc:name="classTest" class="org.mule.example.scripting.IpClient" />
</async>
<cxf:proxy-service service="Weather" doc:name="Weather_webservice"
wsdlLocation="http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl" namespace="http://ws.cdyne.com/WeatherWS/"
payload="envelope"></cxf:proxy-service>
<copy-properties propertyName="SOAPAction" doc:name="Property"></copy-properties>
<cxf:proxy-client doc:name="Weather_webservice"
payload="envelope" />
<outbound-endpoint address="http://wsf.cdyne.com/WeatherWS/Weather.asmx"
exchange-pattern="request-response" doc:name="HTTP"></outbound-endpoint>
</flow>
and IpClient class:
public class IpClient implements Callable,ModelNotificationListener<ModelNotification> {
#Override
public void onNotification(ModelNotification notification) {
// TODO Auto-generated method stub
System.out.println("Notification order event: " + notification.getActionName() );
if(notification.getAction() == ModelNotification.MODEL_DISPOSED || notification.getAction() == ModelNotification.MODEL_STOPPED){
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
ConnectDB c = new ConnectDB("localhost:3306", "accounting", "root", "");
String sql = " INSERT INTO weather (ip, date, CurrentState) VALUES (?,?,?) ";
PreparedStatement ps = null;
try {
ps = c.getConnnection().prepareStatement(sql);
ps.setString(1, "127.0.0.1");
ps.setString(2, dateFormat.format(date).toString());
ps.setString(3, notification.getActionName());
ps.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
c.close();
}
}
}
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
MuleMessage msg = eventContext.getMessage();
String remClient = msg.getProperty("remoteClientAddress", PropertyScope.INVOCATION);
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
ConnectDB c = new ConnectDB("localhost:3306", "accounting", "root", "");
String sql = " INSERT INTO weather (ip, date, CurrentState) VALUES (?,?,?) ";
PreparedStatement ps = c.getConnnection().prepareStatement(sql);
ps.setString(1, remClient);
ps.setString(2, dateFormat.format(date).toString());
ps.setString(3, msg.getMuleContext().getLifecycleManager().getCurrentPhase());
ps.executeUpdate();
c.close();
return msg.getPayload();
}
}
this program just works correctly if I start to run service. for example my service run before suddenly it was dissposed(for example my wsdl(http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl doesn't work)). my log program saved all records in state of start and after dissposing it works similar. if I stoped my service and run it again it works correctly and it saves all records in dissposed mode.
I don't know how to change my program that it saves correctly in runtime.
The (ill named) Initializer bean is not used as a <component> anywhere in the configuration so there's no way its onCall method will ever get called.
If your intention with:
<notification event="COMPONENT-MESSAGE"/>
is to have the Initializer called for each component invocation you then have to make it implement ComponentMessageNotificationListener (like you made it implement ModelNotificationListener).

Mocking ASP.NET MVC Controller properties

I have a MVC controller that loads a resource file and uses Server.MapPath to get the path to the file. I want to mock out the Server property in the controller object using Microsoft Fakes framework (I know how to do this using other frameworks).
Here's the code:
[HttpGet]
public ActionResult GeneratePdf(string reportId)
{
var template = LoadTemplate(reportId);
var document = pdfWriter.Write(GetReportModel(reportId), template);
return File(document, MediaTypeNames.Application.Pdf);
}
private byte[] LoadTemplate(string reportId)
{
var templatePath = Server.MapPath(string.Format("~/ReportTemplates/{0}.docx", reportId));
using(var templateContent = System.IO.File.OpenText(templatePath))
{
return Encoding.Default.GetBytes(templateContent.ReadToEnd());
}
}
The part I'm trying to mock out is the "Server.MapPath" method.
As of Visual Studio 2012 Update 1, you can detour the Controller.Server property using Stubs.
With the following .Fakes file in your test project:
<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/" Diagnostic="true">
<Assembly Name="System.Web" Version="4.0.0.0"/>
<StubGeneration>
<Clear/>
<Add FullName="System.Web.HttpContextBase!"/>
<Add FullName="System.Web.HttpServerUtilityBase!"/>
</StubGeneration>
<ShimGeneration>
<Clear/>
</ShimGeneration>
</Fakes>
You can write the a unit test like this:
[TestMethod]
public void TestMethod1()
{
var target = new TestController();
var serverStub = new StubHttpServerUtilityBase();
serverStub.MapPathString = (path) => path.Replace("~", string.Empty).Replace("/", #"\");
var contextStub = new StubHttpContextBase();
contextStub.ServerGet = () => serverStub;
target.ControllerContext = new ControllerContext();
target.ControllerContext.HttpContext = contextStub;
var result = (FilePathResult) target.Index();
Assert.AreEqual(#"\Content\Test.txt", result.FileName);
}
With the upcoming Update 2, you will also be able to detour Controller.Server property directly using Shims. Here is the additional .Fakes file you will need with this approach.
<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/" Diagnostic="true">
<Assembly Name="System.Web.Mvc" Version="4.0.0.0"/>
<StubGeneration>
<Clear/>
</StubGeneration>
<ShimGeneration>
<Clear/>
<Add FullName="System.Web.Mvc.Controller!"/>
</ShimGeneration>
</Fakes>
And here is the test:
[TestMethod]
public void TestMethod2()
{
using (ShimsContext.Create())
{
var target = new TestController();
var serverStub = new StubHttpServerUtilityBase();
serverStub.MapPathString = (path) => path.Replace("~", string.Empty).Replace("/", #"\");
var controllerShim = new ShimController(target);
controllerShim.ServerGet = () => serverStub;
var result = (FilePathResult)target.Index();
Assert.AreEqual(#"\Content\Test.txt", result.FileName);
}
}
Please note that this approach does not work in the current version (Update 1), due to limitations in Fakes runtime related to assemblies, like System.Web.Mvc that allow partially trusted callers. If you try to run the second test today, you will get a VerificationException.