Confusion on ektron persona management - ektron

i have created a custom connection in dxh but that is not available on persona management site. from this video i understand that i have to create a class library for my custom connection. Is there any demo code available for this custom library?
i am stuck with the login management of dxh and persona, and how is this attributes working?
my code
using Attribute = Ektron.PersonaManagement.Common.Attribute;
public class ETPersona : PersonaAttributeProvider
{
public override IEnumerable<Attribute> GetAttributes()
{
return new List<Attribute>() {
new Attribute() {
DataSource = "test",
DataSourceId = "test",
Id = "test",
Name = new LocalizableText("test","test"),
Type =FieldType.String,
Options = new List<LocalizableText>(){new LocalizableText("test","test")}
}
};
}
public override UserAttributeData GetUserAttributeData(VisitorContext context)
{
return new UserAttributeData()
{
Attributes = new List<UserAttribute>() { new UserAttribute() { } },
HaveUserData = true,
UserKey = ""
};
}
}

Please see Ektron's forum discussion here for information:
http://developer.ektron.com/Forums/?v=t&t=1975

Related

How can I connect my databse by using LINQtoSPARQL for writing linq based services?

The following is the code of TestDataProvider class in LINQtoSPARQL (githublinkk). Here, data is taken from string or file.
namespace LINQtoSPARQLSpace.Tests
{
public static class TestDataProvider
{
public static ISPARQLQueryable<T> GetQuerable<T>(string data,
bool autoquotation = true,
bool treatUri = true,
IEnumerable<Prefix> prefixes = null,
bool skipTriplesWithEmptyObject = false,
bool mindAsterisk = false,
bool useStore = false,
string defaultGraphUri = "http://test.org/defaultgraph")
{
DynamicSPARQLSpace.dotNetRDF.Connector connector = null;
if (useStore)
{
var store = new VDS.RDF.TripleStore();
store.LoadFromString(data);
connector = new Connector(new InMemoryDataset(store, new Uri(defaultGraphUri)));
}
else
{
var graph = new VDS.RDF.Graph();
graph.LoadFromFile(data);
connector = new Connector(new InMemoryDataset(graph));
}
dynamic dyno = DynamicSPARQL.CreateDyno(connector.GetQueryingFunction(),
updateFunc: connector.GetUpdateFunction(),
autoquotation: autoquotation,
treatUri: treatUri,
prefixes:prefixes,
skipTriplesWithEmptyObject:skipTriplesWithEmptyObject,
mindAsterisk:mindAsterisk);
return new SPARQLQuery<T>(dyno);
}
}
}
Now, I want to connect my database (GraphDB ontotext). for now, I am able to connect my database with the help of following lines:
Options.ForceHttpBasicAuth = true;
var store2 = new VDS.RDF.Query.SparqlRemoteEndpoint(new Uri("http://localhost:7200/repositories/786"));
store2.SetCredentials("admin", "admin");
Now, how can I pass this SparqlRemoteEndpoint object to Connector class object? am I going in the right way to connect?
Please Help.

Swashbuckle 5 and multipart/form-data HelpPages

I am stuck trying to get Swashbuckle 5 to generate complete help pages for an ApiController with a Post request using multipart/form-data parameters. The help page for the action comes up in the browser, but there is not included information on the parameters passed in the form. I have created an operation filter and enabled it in SwaggerConfig, the web page that includes the URI parameters, return type and other info derived from XML comments shows in the browser help pages; however, nothing specified in the operation filter about the parameters is there, and the help page contains no information about the parameters.
I must be missing something. Are there any suggestion on what I may have missed?
Operation filter code:
public class AddFormDataUploadParamTypes : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) {
if (operation.operationId == "Documents_Upload")
{
operation.consumes.Add("multipart/form-data");
operation.parameters = new[]
{
new Parameter
{
name = "anotherid",
#in = "formData",
description = "Optional identifier associated with the document.",
required = false,
type = "string",
format = "uuid"
},
new Parameter
{
name = "documentid",
#in = "formData",
description = "The document identifier of the slot reserved for the document.",
required = false,
type = "string",
format = "uuid"
},
new Parameter
{
name = "documenttype",
#in = "formData",
description = "Specifies the kind of document being uploaded. This is not a file name extension.",
required = true,
type = "string"
},
new Parameter
{
name = "emailfrom",
#in = "formData",
description = "A optional email origination address used in association with the document if it is emailed to a receiver.",
required = false,
type = "string"
},
new Parameter
{
name = "emailsubject",
#in = "formData",
description = "An optional email subject line used in association with the document if it is emailed to a receiver.",
required = false,
type = "string"
},
new Parameter
{
name = "file",
#in = "formData",
description = "File to upload.",
required = true,
type = "file"
}
};
}
}
}
With Swashbuckle v5.0.0-rc4 methods listed above do not work. But by reading OpenApi spec I have managed to implement a working solution for uploading a single file. Other parameters can be easily added:
public class FileUploadOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var isFileUploadOperation =
context.MethodInfo.CustomAttributes.Any(a => a.AttributeType == typeof(YourMarkerAttribute));
if (!isFileUploadOperation) return;
var uploadFileMediaType = new OpenApiMediaType()
{
Schema = new OpenApiSchema()
{
Type = "object",
Properties =
{
["uploadedFile"] = new OpenApiSchema()
{
Description = "Upload File",
Type = "file",
Format = "binary"
}
},
Required = new HashSet<string>()
{
"uploadedFile"
}
}
};
operation.RequestBody = new OpenApiRequestBody
{
Content =
{
["multipart/form-data"] = uploadFileMediaType
}
};
}
}
I presume you figured out what your problem was. I was able to use your posted code to make a perfect looking 'swagger ui' interface complete with the file [BROWSE...] input controls.
I only modified your code slightly so it is applied when it detects my preferred ValidateMimeMultipartContentFilter attribute stolen from Damien Bond. Thus, my slightly modified version of your class looks like this:
public class AddFormDataUploadParamTypes<T> : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline();
var supportsDesiredFilter = actFilters.Select(f => f.Instance).OfType<T>().Any();
if (supportsDesiredFilter)
{
operation.consumes.Add("multipart/form-data");
operation.parameters = new[]
{
//other parameters omitted for brevity
new Parameter
{
name = "file",
#in = "formData",
description = "File to upload.",
required = true,
type = "file"
}
};
}
}
}
Here's my Swagger UI:
FWIW:
My NuGets
<package id="Swashbuckle" version="5.5.3" targetFramework="net461" />
<package id="Swashbuckle.Core" version="5.5.3" targetFramework="net461" />
Swagger Config Example
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.Schemes(new[] { "https" });
// Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to
// hold additional metadata for an API. Version and title are required but you can also provide
// additional fields by chaining methods off SingleApiVersion.
//
c.SingleApiVersion("v1", "MyCorp.WebApi.Tsl");
c.OperationFilter<MyCorp.Swashbuckle.AddFormDataUploadParamTypes<MyCorp.Attr.ValidateMimeMultipartContentFilter>>();
})
.EnableSwaggerUi(c =>
{
// If your API supports ApiKey, you can override the default values.
// "apiKeyIn" can either be "query" or "header"
//
//c.EnableApiKeySupport("apiKey", "header");
});
}
}
UPDATE March 2019
I don't have quick access to the original project above, but, here's an example API controller from a different project...
Controller signature:
[ValidateMimeMultipartContentFilter]
[SwaggerResponse(HttpStatusCode.OK, Description = "Returns JSON object filled with descriptive data about the image.")]
[SwaggerResponse(HttpStatusCode.NotFound, Description = "No appropriate equipment record found for this endpoint")]
[SwaggerResponse(HttpStatusCode.BadRequest, Description = "This request was fulfilled previously")]
public async Task<IHttpActionResult> PostSignatureImage(Guid key)
You'll note that there's no actual parameter representing my file in the signature, you can see below that I just spin up a MultipartFormDataStreamProvider to suck out the incoming POST'd form data.
Controller Body:
var signatureImage = await db.SignatureImages.Where(img => img.Id == key).FirstOrDefaultAsync();
if (signatureImage == null)
{
return NotFound();
}
if (!signatureImage.IsOpenForCapture)
{
ModelState.AddModelError("CaptureDateTime", $"This equipment has already been signed once on {signatureImage.CaptureDateTime}");
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
string fileName = String.Empty;
string ServerUploadFolder = System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/");
DirectoryInfo di = new DirectoryInfo(ServerUploadFolder + key.ToString());
if (di.Exists == true)
ModelState.AddModelError("id", "It appears an upload for this item is either in progress or has already occurred.");
else
di.Create();
var fullPathToFinalFile = String.Empty;
var streamProvider = new MultipartFormDataStreamProvider(di.FullName);
await Request.Content.ReadAsMultipartAsync(streamProvider);
foreach (MultipartFileData fileData in streamProvider.FileData)
{
if (string.IsNullOrEmpty(fileData.Headers.ContentDisposition.FileName))
{
return StatusCode(HttpStatusCode.NotAcceptable);
}
fileName = cleanFileName(fileData.Headers.ContentDisposition.FileName);
fullPathToFinalFile = Path.Combine(di.FullName, fileName);
File.Move(fileData.LocalFileName, fullPathToFinalFile);
signatureImage.Image = File.ReadAllBytes(fullPathToFinalFile);
break;
}
signatureImage.FileName = streamProvider.FileData.Select(entry => cleanFileName(entry.Headers.ContentDisposition.FileName)).First();
signatureImage.FileLength = signatureImage.Image.LongLength;
signatureImage.IsOpenForCapture = false;
signatureImage.CaptureDateTime = DateTimeOffset.Now;
signatureImage.MimeType = streamProvider.FileData.Select(entry => entry.Headers.ContentType.MediaType).First();
db.Entry(signatureImage).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
//cleanup...
File.Delete(fullPathToFinalFile);
di.Delete();
}
catch (DbUpdateConcurrencyException)
{
if (!SignatureImageExists(key))
{
return NotFound();
}
else
{
throw;
}
}
char[] placeHolderImg = paperClipIcon_svg.ToCharArray();
signatureImage.Image = Convert.FromBase64CharArray(placeHolderImg, 0, placeHolderImg.Length);
return Ok(signatureImage);
Extending #bkwdesign very useful answer...
His/her code includes:
//other parameters omitted for brevity
You can actually pull all the parameter information (for the non-multi-part form parameters) from the parameters to the filter. Inside the check for supportsDesiredFilter, do the following:
if (operation.parameters.Count != apiDescription.ParameterDescriptions.Count)
{
throw new ApplicationException("Inconsistencies in parameters count");
}
operation.consumes.Add("multipart/form-data");
var parametersList = new List<Parameter>(apiDescription.ParameterDescriptions.Count + 1);
for (var i = 0; i < apiDescription.ParameterDescriptions.Count; ++i)
{
var schema = schemaRegistry.GetOrRegister(apiDescription.ParameterDescriptions[i].ParameterDescriptor.ParameterType);
parametersList.Add(new Parameter
{
name = apiDescription.ParameterDescriptions[i].Name,
#in = operation.parameters[i].#in,
description = operation.parameters[i].description,
required = !apiDescription.ParameterDescriptions[i].ParameterDescriptor.IsOptional,
type = apiDescription.ParameterDescriptions[i].ParameterDescriptor.ParameterType.FullName,
schema = schema,
});
}
parametersList.Add(new Parameter
{
name = "fileToUpload",
#in = "formData",
description = "File to upload.",
required = true,
type = "file"
});
operation.parameters = parametersList;
first it checks to make sure that the two arrays being passed in are consistent. Then it walks through the arrays to pull out the required info to put into the collection of Swashbuckle Parameters.
The hardest thing was to figure out that the types needed to be registered in the "schema" in order to have them show up in the Swagger UI. But, this works for me.
Everything else I did was consistent with #bkwdesign's post.

NHibernate Dynamic Component Default Value Issue

All of my entities (that are mapped to a database table) inherit from an entity class with a dynamic component on it called Attributes e.g.:
public abstract class Entity<T> {
public virtual T Id { get; set; }
private IDictionary _attributes;
public virtual IDictionary Attributes {
get { return _attributes ?? (_attributes = new Hashtable()); }
set { _attributes = value; }
}
}
The Attributes collection allows me to add extra fields to each entity without directly changing the entity itself. This allows me to make my application more modular.
For example say I have the following entity:
public class User : Entity<int> {
public virtual string Name { get; set; }
}
Now say I have a Forum module which needs a NumPosts property against the User. I would add the field against the Users table in the database. This field is non nullable and has a default value of 0. I then map the field using the dynamic component against the User entity.
However when I try inserting the user by saying:
session.Save(new User() { Name = "Test" });
It throws an error as it's expecting me to set a value for NumPosts and the generated SQL would be something like:
INSERT INTO Users (Name, NumPosts) VALUES ('Test', NULL)
However NumPosts does not allow nulls and hence the error. Ideally I'd like it to say the following if the Attributes collection does not contain an entry for NumPosts:
INSERT INTO Users (Name) VALUES ('Test')
An alternative is to say the following which would work fine:
session.Save(new User() { Name = "Test", Attributes = new Hashtable() { { "NumPosts", 0 } } });
The problem I have is that I don't want the modules to have a dependency on each other and I can't really say this.
For reference here's a bare bones version of session factory method which maps the NumPosts field:
return Fluently.Configure()
...
.ExposeConfiguration(c => {
// Get the persistent class
var persistentClass = c.GetClassMapping("User");
// Create the attributes component
var component = new Component(persistentClass);
// Create a simple value
var simpleValue = new SimpleValue(persistentClass.Table);
// Set the type name
simpleValue.TypeName = "Int32";
// Create a new db column specification
var column = new Column("NumPosts");
column.Value = simpleValue;
column.Length = 10;
column.IsNullable = false;
column.DefaultValue = "0";
// Add the column to the value
simpleValue.AddColumn(column);
// Ad the value to the component
component.AddProperty(new Property() { Name = column.Name, Value = simpleValue });
// Add the component property
persistentClass.AddProperty(new Property() { Name = "Attributes", Value = component });
})
.BuildConfiguration();
I'd appreciate if someone could let me know if this is possible. Thanks
You know how to make it working as described above:
... An alternative is to say the following which would work fine:
session.Save(new User()
{
Name = "Test", Attributes = new Hashtable() { { "NumPosts", 0 } }
});
... The problem I have is that I don't want the modules to have a dependency on each other and I can't really say this...
In case, that the biggest issue is the explicit Attributes initialization ("...I don't want the modules to have a dependency...") we can use:
12.2. Event system
So, with Listener like this:
[Serializable]
public class MyPersistListener : NHibernate.Event.ISaveOrUpdateEventListener
{
public void OnSaveOrUpdate(SaveOrUpdateEvent #event)
{
var entity = #event.Entity as Entity<int>; // some interface IHaveAttributes
if (entity == null) // would be more appropriate
{
return;
}
var numPosts = entity.Attributes["NumPosts"] as int?;
if (numPosts.HasValue)
{
return;
}
entity.Attributes["NumPosts"] = 0;
}
}
Based on this doc snippet:
Configuration cfg = new Configuration();
ILoadEventListener[] stack = new ILoadEventListener[] { new MyLoadListener(), new DefaultLoadEventListener() };
cfg.EventListeners.LoadEventListeners = stack;
This should be the init in our case:
.ExposeConfiguration(c => {
var stack = new ISaveOrUpdateEventListener [] { new MyPersistListener() };
c.EventListeners.SaveEventListeners= stack;

Web API OData Typeless support for $select query option

I am working with the new typeless support in ASP.NET Web API 2 OData. I am interested in providing support for the $select query option. How do I omit the structural properties from the EdmEntityObject that were not selected by the $select query option?
The following is a sample of the Web API Configuration for a very simple example working with a typeless model.
public static IEdmModel BuildEdmModel()
{
var model = new EdmModel();
var container = new EdmEntityContainer("Model", "OData");
var product = new EdmEntityType("Model", "Product");
var productKey = product.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Guid);
product.AddKeys(productKey);
product.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
product.AddStructuralProperty("Price", EdmPrimitiveTypeKind.Double);
model.AddElement(product);
model.AddElement(container);
model.SetIsDefaultEntityContainer(container, true);
container.AddEntitySet("Products", product);
return model;
}
public static void Register(HttpConfiguration config)
{
config.Routes.MapODataRoute("ODataRoute", "odata", BuildEdmModel());
}
The following is a partial snippet from a simple ODataController
public EdmEntityObjectCollection Get()
{
var path = Request.GetODataPath();
var edmType = path.EdmType;
var collectionType = edmType as IEdmCollectionType;
var entityType = collectionType.ElementType.AsEntity();
var entitySetName = entityType.EntityDefinition().Name;
var model = Request.GetEdmModel();
var queryContext = new ODataQueryContext(Request.GetEdmModel(), entityType.Definition);
var queryOptions = new ODataQueryOptions(queryContext, Request);
return GetData(Request.GetEdmModel(), queryOptions);
}
public static EdmEntityObjectCollection GetData(IEdmModel edmModel, ODataQueryOptions queryOptions)
{
var selectedPropertyNames = new string[0];
// determine the selected property names
if (queryOptions.SelectExpand != null && queryOptions.SelectExpand.SelectExpandClause != null && (!queryOptions.SelectExpand.SelectExpandClause.AllSelected || queryOptions.SelectExpand.SelectExpandClause.SelectedItems.OfType<WildcardSelectItem>().Any()))
{
selectedPropertyNames = queryOptions.SelectExpand.RawSelect.Split(',');
}
// TODO: Now that we have the selected properties, how do I remove the structural properties from the EdmEntityObject that were not selected by the $select query option?
var productSchemaType = edmModel.FindDeclaredType(string.Format("{0}.Product", "Model"));
var productEntityType = productSchemaType as IEdmEntityType;
var productEntityTypeReference = new EdmEntityTypeReference(productEntityType, true);
var products = new EdmEntityObjectCollection(new EdmCollectionTypeReference(new EdmCollectionType(productEntityTypeReference), true));
var productWindows = new EdmEntityObject(productEntityTypeReference);
productWindows.TrySetPropertyValue("ID", new Guid("52D811A0-9065-4B83-A2E8-0248FBA9FBF5"));
productWindows.TrySetPropertyValue("Name", "Microsoft Windows 8");
productWindows.TrySetPropertyValue("Price", 179.99);
var productOffice = new EdmEntityObject(productEntityTypeReference);
productOffice.TrySetPropertyValue("ID", new Guid("CB39EBD0-4751-4D5F-A76C-78FCC7A9CE1A"));
productOffice.TrySetPropertyValue("Name", "Microsoft Office 2013");
productOffice.TrySetPropertyValue("Price", 399.99);
products.Add(productWindows);
products.Add(productOffice);
return products;
}
This will output:
{
"odata.metadata":"http://localhost:59511/odata/$metadata#Products","value":[
{
"ID":"52d811a0-9065-4b83-a2e8-0248fba9fbf5","Name":"Microsoft Windows 8","Price":179.99
},{
"ID":"cb39ebd0-4751-4d5f-a76c-78fcc7a9ce1a","Name":"Microsoft Office 2013","Price":399.99
}
]
}
If the user applies a $select query option, for example /odata/Products?$select=Name. This should result in the following output:
{
"odata.metadata":"http://localhost:59511/odata/$metadata#Products","value":[
{
"Name":"Microsoft Windows 8"
},{
"Name":"Microsoft Office 2013"
}
]
}
Any help would be greatly appreciated
The following works for me.
var oDataProperties = Request.ODataProperties()
oDataProperties.SelectExpandClause = queryOptions.SelectExpand.SelectExpandClause;
The extension function is in System.web.OData.dll v5.2.0.0.
Here's my code.
private void ApplySelectExpand(SelectExpandQueryOption selectExpand)
{
if (selectExpand != null)
{
Request.SetSelectExpandClause(selectExpand.SelectExpandClause);
}
}
There are two ways to solve your problem if I understood your question correctly.
Call the ApplyTo method of ODataQueryOptions on the IQueryable result
return queryOptions.ApplyTo(products);
Add attribute Queryable on the GetData method and let WebAPI handles the query option
[Queryable]
public static EdmEntityObjectCollection GetData(IEdmModel edmModel)
{...}

How to change Owin.AuthenticationIdentityManager's PasswordValidator settings?

This autogenerated code registers a new user:
var manager = new AuthenticationIdentityManager(new IdentityStore());
User u = new User(userName) { UserName = userName };
IdentityResult result = manager.Users.CreateLocalUser(u, Password.Text);
if (result.Success)
{ ... }
How can we change password validation settings?
This is what I've found using dotPeek:
AuthenticationIdentityManager class instance contains UserManager which validates a password using PasswordValidator:
From class Microsoft.AspNet.Identity.UserManager:
result = this.PasswordValidator.Validate(password);
internal IStringValidator PasswordValidator
{
get
{
return this.Manager.Settings.GetIdentityOptions().PasswordValidator;
}
}
Class Microsoft.AspNet.Identity.IdentityOptions:
public IdentityOptions()
{
this._defaultPasswordValidator = new IdentityOptions.DefaultPasswordValidator(this);
this._defaultUserNameValidator = new IdentityOptions.DefaultUserNameValidator(this);
this.MinRequiredPasswordLength = 6;
this.LocalLoginProvider = "Local";
}
public IStringValidator PasswordValidator
{
get
{
return this._passwordValidator ?? (IStringValidator) this._defaultPasswordValidator;
}
set
{
this._passwordValidator = value;
}
}
I cannot find where IdentityOptions instance can be accessed or replaced. Is there any example or documentation?
RTM version seems to have dropped AuthenticationIdentityManager. Try upgrading the to latest pre-release version.
In the latest version, you can provide PasswordValidator implementation to UserManager. This will enable customization of password strength validation in your app.
ASP.NET Identity nighlty packages are now available on MyGet