I want a write a custom function to find a particular property from identity user model.
Say I want to find a user with a specified phone number.
How to do so..???
You need to extend the UserStore class, something like below
public interface IUserCustomStore<TUser> : IUserStore<TUser, string>, IDisposable where TUser : class, Microsoft.AspNet.Identity.IUser<string>
{
Task<TUser> FindByPhoneNumberAsync(string phoneNumber);
}
namespace AspNet.Identity.MyCustomStore
{
public class UserStore<TUser> : Microsoft.AspNet.Identity.EntityFramework.UserStore<TUser>, IUserCustomStore<TUser>
where TUser : Microsoft.AspNet.Identity.EntityFramework.IdentityUser
{
public UserStore(ApplicationDbContext context)
: base(context)
{
}
public Task<TUser> FindByPhoneNumberAsync(string phoneNumber)
{
//Your Implementation
}
}
public class UserStore<TUser> : IUserCustomStore<TUser> where TUser:IdentityUser
{
public virtual Task<TUser> FindByPhoneNumberAsync(string phoneNumber)
{
return _Users.Find(u => u.PhoneNumber == phoneNumber).FirstOrDefaultAsync();
}
}
}
Replace all occurrence of
using Microsoft.AspNet.Identity.EntityFramework
with
using AspNet.Identity.MyCustomStore
And then in the IdentityConfig.cs add a new method to ApplicationUserManager
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
//LEAVE ALL THE METHODS AS IT IS
public virtual Task<ApplicationUser> FindByPhoneNumberUserManagerAsync(string phoneNumber)
{
IUserCustomStore<ApplicationUser> userCustomStore = this.Store as IUserCustomStore<ApplicationUser>;
if (phoneNumber == null)
{
throw new ArgumentNullException("phoneNumber");
}
return userCustomStore.FindByPhoneNumberAsync(phoneNumber);
}
}
You can now call this in the controller like
var user = await UserManager.FindByPhoneNumberUserManagerAsync(model.phoneNumber);
(assuming you have added the phoneNumber property to RegisterViewModel)
Hope this helps.
Related
I'm an Orchard newbie and I'm having difficulty trying to get the form data when a new item is created.
What I have is a module that creates a menu item on the admin dashboard. That menu item will load a page where a user can enter a new "Coach".
There are 3 things needed for a coach, first name, last name and email.
Here's the code I have implemented for this...
migrations.cs
public class SDSDataMigration : DataMigrationImpl
{
public int Create()
{
SchemaBuilder..CreateTable("CoachPartRecord", table => table.ContentPartRecord()
.Column("FirstName", DbType.AnsiString, c => c.WithLength(50))
.Column("LastName", DbType.AnsiString, c => c.WithLength(50))
.Column("Email", DbType.AnsiString, c => c.WithLength(200)))
ContentDefinitionManager.AlterPartDefinition("CoachPart", part => part
.WithField("FirstName", f => f.OfType("TextField"))
.WithField("LastName", f => f.OfType("TextField"))
.WithField("Email", f => f.OfType("TextField"))
);
ContentDefinitionManager.AlterTypeDefinition("Coach", type => type.WithPart("CommonPart")
.WithPart("CoachPart"));
return 1;
}
}
parts/records
public class CoachPartRecord : ContentPartRecord
{
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Email { get; set; }
}
public class CoachPart : ContentPart<CoachPartRecord>
{
public string FirstName
{
get { return Record.FirstName; }
set { Record.FirstName = value; }
}
public string LastName
{
get { return Record.LastName; }
set { Record.LastName = value; }
}
public string Email
{
get { return Record.Email; }
set { Record.Email = value; }
}
}
view for creating editor
#{ Layout.Title = T("Add Coach").ToString(); }
#using (Html.BeginFormAntiForgeryPost()) {
// Model is a Shape, calling Display() so that it is rendered using the most specific template for its Shape type
#Display(Model)
}
handler
public class CoachPartHandler : ContentHandler
{
public CoachPartHandler(IRepository<CoachPartRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
}
}
driver
protected override DriverResult Editor(CoachPart part, IUpdateModel updater, dynamic shapeHelper)
{
updater.TryUpdateModel(part, Prefix, null, null);
return Editor(part, shapeHelper);
}
controller (for dashboard menu item)
public ActionResult Create()
{
var coach = _services.ContentManager.New("Coach");
var model = _services.ContentManager.BuildEditor(coach);
return View(model);
}
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST()
{
var contentItem = _services.ContentManager.New("Coach");
_services.ContentManager.Publish(contentItem);
return View("Index");
}
Right now I can get the form to appear to create a new coach. When I hit "Publish" all of the fields (i.e. FirstName, LastName, Email) for the CoachPart parameter in the driver are null.
I can look at the http request and I can see the values I put on the form, but they're not making it to the CoachPart.
Any ideas why the CoachPart fields aren't getting filed in?
Thanks!
First of all, you are defining the properties on your own record. Therefore you don't need new textfields attached to your part, so you should remove this:
ContentDefinitionManager.AlterPartDefinition("CoachPart", part => part
.WithField("FirstName", f => f.OfType("TextField"))
.WithField("LastName", f => f.OfType("TextField"))
.WithField("Email", f => f.OfType("TextField")));
Secondly, because you use your custom controller istead of orchard's content controller, you must implement the IUpdateModel and act on it:
[Admin]
public class MyController : Controller, IUpdateModel {
private readonly IContentManager _contentManager;
private readonly ITransactionManager _transactionManager;
public MyController(IContentManager contentManager,
ITransactionManager transactionManager) {
_contentManager = contentManager;
_transactionManager = transactionManager;
}
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST()
{
var contentItem = _contentManager.New<CoachPart>("Coach");
// The implementation of IUpdateModel is necessary for this next line:
var model = _contentManager.UpdateEditor(contentItem, this);
if (!ModelState.IsValid) {
_transactionManager.Cancel();
return View(model);
}
_contentManager.Publish(contentItem);
return View("Index");
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
}
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
ModelState.AddModelError(key, errorMessage.ToString());
}
}
I'm trying to register a mapping convention to handle mapping from classes with Pascal Case names to classes with underscore names with postfix and prefix, and back again. I've tried to follow examples, but cannot get my head around how it's supposed to work.
This is one of the many things I've tried, that looks like it should work (in my opinion :)), but it doesn't seem to do anything:
public class PascalCaseEntity
{
public string CallingSystem { get; set; }
}
public class UnderscoreWithPrefixAndPostfixEntity
{
public string p_calling_system_ { get; set; }
}
public class PartsMappings
{
public void Apply()
{
Mapper.Initialize(cfg =>
{
cfg.AddProfile<FromUnderscoreMapping>();
cfg.AddProfile<ToUnderscoreMapping>();
cfg.CreateMap<PascalCaseEntity, UnderscoreWithPrefixAndPostfixEntity>()
.WithProfile("ToUnderscoreMapping");
cfg.CreateMap<UnderscoreWithPrefixAndPostfixEntity, PascalCaseEntity>()
.WithProfile("FromUnderscoreMapping");
});
}
}
public class FromUnderscoreMapping : Profile
{
protected override void Configure()
{
RecognizePrefixes("p_");
RecognizePostfixes("_");
SourceMemberNamingConvention = new LowerUnderscoreNamingConvention();
DestinationMemberNamingConvention = new PascalCaseNamingConvention();
}
public override string ProfileName
{
get { return "FromUnderscoreMapping"; }
}
}
public class ToUnderscoreMapping : Profile
{
protected override void Configure()
{
RecognizeDestinationPrefixes("p_");
RecognizeDestinationPostfixes("_");
SourceMemberNamingConvention = new PascalCaseNamingConvention();
DestinationMemberNamingConvention = new LowerUnderscoreNamingConvention();
}
public override string ProfileName
{
get { return "ToUnderscoreMapping"; }
}
}
What am I missing here?
I finally found a working solution. I created two profiles, one for each "direction", and added the mappings to them.
I'm not too happy with it, since I'd rather have the mappings in the same file (grouping them on business area). But at least it works... :)
I also tried putting the registrations in the same Profile, and using the .WithProfile("ToUnderscoreWithPrefix") method, but I didn't get that to work.
Mapper.Initialize(cfg =>
{
cfg.AddProfile(new ToUnderscoreWithPrefixMappings());
cfg.AddProfile(new FromUnderscoreWithPrefixMappings());
});
public class ToUnderscoreWithPrefixMappings : Profile
{
protected override void Configure()
{
RecognizeDestinationPrefixes("P", "p");
SourceMemberNamingConvention = new PascalCaseNamingConvention();
DestinationMemberNamingConvention = new LowerUnderscoreNamingConvention();
CreateMap<PascalCaseEntity, UnderscoreWithPrefixAndPostfixEntity>();
}
public override string ProfileName { get; } = "ToUnderscoreWithPrefix";
}
public class FromUnderscoreWithPrefixMappings : Profile
{
protected override void Configure()
{
RecognizePrefixes("P_", "p_");
RecognizePostfixes("_");
SourceMemberNamingConvention = new LowerUnderscoreNamingConvention();
DestinationMemberNamingConvention = new PascalCaseNamingConvention();
CreateMap<UnderscoreWithPrefixAndPostfixEntity, PascalCaseEntity>();
}
public override string ProfileName { get; } = "FromUnderscoreWithPrefix";
}
I have created a custom content type called 'AccessFolder'. I can see it in the list of content types and can create a new one. When I create a new AccessFolder, I get my editor template that I created for it. After I enter the information and click save, I'm directed to a Not Found page however the indicator message tells me my AccessFolder was created successfully.
In the driver, I can see the model after it is bound using the updater.TryUpdateModel. The correct values are assigned to the model's properties.
It just never gets to the database.
AccessFolderPart:
public class AccessFolderPart : ContentPart<AccessFolderPartRecord>
{
public virtual string Name
{
get { return Record.Name; }
set { Record.Name = value; }
}
public virtual IEnumerable<RoleRecord> DownloadRoles
{
get { return Record.DownloadRoles.Select(x => x.RoleRecord); }
}
}
AccessFolderPartRecord
public class AccessFolderPartRecord : ContentPartRecord
{
public virtual string Name { get; set; }
public virtual List<ContentAccessFolderRoleRecord> DownloadRoles { get; set; }
}
Relevant Pieces of AccessFolderPartDriver
protected override DriverResult Editor(AccessFolderPart part, dynamic shapeHelper)
{
var viewModel = new AccessFolderViewModel(part, _roleService.GetRoles());
return ContentShape("Parts_AccessFolder_Edit", () =>
shapeHelper.EditorTemplate(TemplateName: templateName, Model: viewModel, Prefix: Prefix));
}
protected override DriverResult Editor(AccessFolderPart part, Orchard.ContentManagement.IUpdateModel updater, dynamic shapeHelper)
{
var viewModel = new AccessFolderViewModel { Part = part };
updater.TryUpdateModel(viewModel, Prefix, null, null);
if (part.ContentItem.Id != 0)
{
_roleService.UpdateRolesForAccessFolder(part.ContentItem, part.DownloadRoles);
}
return Editor(part, shapeHelper);
}
I've been stuck on this since Friday. I've created custom types before and never had any problems with it. I can't see what I've done wrong here.
Update - Added content Handler class
Here's the one line for the handler:
public class AccessFolderPartHandler : ContentHandler
{
public AccessFolderPartHandler(IRepository<AccessFolderPartRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
}
}
I Think you are missing the proper mapping on your driver:
if (updater.TryUpdateModel(viewModel, Prefix, null, null))
{
part.Name= viewModel.Name;
if (part.ContentItem.Id != 0)
{
_roleService.UpdateRolesForAccessFolder(part.ContentItem, part.DownloadRoles);
}
}
I was playin' around with ServiceStack and was wondering if it supported this scenario. I'm using generics in my request types so that many DTOs that inherit from a common interface will support the same basic methods [ like... GetById(int Id) ].
Using a request type specific to a single kind of DTO works, but breaks the generics nice-ness...
var fetchedPerson = client.Get<PersonDto>(new PersonDtoGetById() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson.Id)); //PASS
Mapping a route to the generic also works:
Routes.Add<DtoGetById<PersonDto>>("/persons/{Id}", ApplyTo.Get);
...
var fetchedPerson2 = client.Get<PersonDto>(string.Format("/persons/{0}", person.Id));
Assert.That(person.Id, Is.EqualTo(fetchedPerson2.Id)); //PASS
But using the end-to-end generic request type fails:
var fetchedPerson3 = client.Get<PersonDto>(new DtoGetById<PersonDto>() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson3.Id)); //FAIL
I wonder if I'm just missing something, or if i'm trying to abstract just ooone layer too far... :)
Below is a complete, failing program using NUnit, default ServiceStack stuff:
namespace ssgenerics
{
using NUnit.Framework;
using ServiceStack.ServiceClient.Web;
using ServiceStack.ServiceHost;
using ServiceStack.ServiceInterface;
using ServiceStack.WebHost.Endpoints;
[TestFixture]
class Program
{
public static PersonDto GetNewTestPersonDto()
{
return new PersonDto()
{
Id = 123,
Name = "Joe Blow",
Occupation = "Software Developer"
};
}
static void Main(string[] args)
{}
[Test]
public void TestPutGet()
{
var listeningOn = "http://*:1337/";
var appHost = new AppHost();
appHost.Init();
appHost.Start(listeningOn);
try
{
var BaseUri = "http://localhost:1337/";
var client = new JsvServiceClient(BaseUri);
var person = GetNewTestPersonDto();
client.Put(person);
var fetchedPerson = client.Get<PersonDto>(new PersonDtoGetById() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson.Id));
var fetchedPerson2 = client.Get<PersonDto>(string.Format("/persons/{0}", person.Id));
Assert.That(person.Id, Is.EqualTo(fetchedPerson2.Id));
Assert.That(person.Name, Is.EqualTo(fetchedPerson2.Name));
Assert.That(person.Occupation, Is.EqualTo(fetchedPerson2.Occupation));
var fetchedPerson3 = client.Get<PersonDto>(new DtoGetById<PersonDto>() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson3.Id));
Assert.That(person.Name, Is.EqualTo(fetchedPerson3.Name));
Assert.That(person.Occupation, Is.EqualTo(fetchedPerson3.Occupation));
}
finally
{
appHost.Stop();
}
}
}
public interface IDto : IReturnVoid
{
int Id { get; set; }
}
public class PersonDto : IDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Occupation { get; set; }
}
public class DtoGetById<T> : IReturn<T> where T : IDto { public int Id { get; set; } }
public class PersonDtoGetById : IReturn<PersonDto> { public int Id { get; set; } }
public abstract class DtoService<T> : Service where T : IDto
{
public abstract T Get(DtoGetById<T> Id);
public abstract void Put(T putter);
}
public class PersonService : DtoService<PersonDto>
{
public override PersonDto Get(DtoGetById<PersonDto> Id)
{
//--would retrieve from data persistence layer
return Program.GetNewTestPersonDto();
}
public PersonDto Get(PersonDtoGetById Id)
{
return Program.GetNewTestPersonDto();
}
public override void Put(PersonDto putter)
{
//--would persist to data persistence layer
}
}
public class AppHost : AppHostHttpListenerBase
{
public AppHost()
: base("Test HttpListener",
typeof(PersonService).Assembly
) { }
public override void Configure(Funq.Container container)
{
Routes.Add<DtoGetById<PersonDto>>("/persons/{Id}", ApplyTo.Get);
}
}
}
No, It's a fundamental concept in ServiceStack that each Service requires its own unique Request DTO, see this answer for more examples on this.
You could do:
[Route("/persons/{Id}", "GET")]
public class Persons : DtoGetById<Person> { ... }
But I strongly advise against using inheritance in DTOs. Property declaration is like a DSL for a service contract and its not something that should be hidden.
For more details see this answer on the purpose of DTO's in Services.
I'm new with orchard.
To learn orchard module development, I am following documentation to try to create a commerce module.
The module consists of product part and product type, which has product part.
When I try to save data in following method:
public ActionResult Create(FormCollection input)
{
var product = contentManager.New<ProductPart>("Product");
product.Description = input["Description"];
product.Sku = input["Sku"];
product.Price =Convert.ToDecimal(input["Price"]);
if (!ModelState.IsValid)
{
return View(product);
}
contentManager.Create(product);
return RedirectToAction("Index");
}
I am getting an error that specific cast is Invalid and part(ContentPart) is null.
public static T New<T>(this IContentManager manager, string contentType)
where T : class, IContent {
var contentItem = manager.New(contentType);
if (contentItem == null)
return null;
var part = contentItem.Get<T>();
if (part == null)
throw new InvalidCastException();
return part;
}
I used content type Product and I have ProductRecord class for storage data, as below:
public class ProductRecord:ContentPartRecord
{
// public virtual int Id { get; set; }
public virtual string Sku { get; set; }
public virtual string Description { get; set; }
public virtual decimal Price { get; set; }
}
public class ProductPart : ContentPart<ProductRecord>
{
/*
public int Id
{
get { return Record.Id; }
set{Record.Id = value;}
}
*/
[Required]
public string Sku
{
get { return Record.Sku; }
set { Record.Sku = value; }
}
[Required]
public string Description
{
get { return Record.Description; }
set{ Record.Description = value;}
}
[Required]
public decimal Price
{
get { return Record.Price; }
set { Record.Price = value; }
}
}
Can anybody tell me what my problem is?
I'm just guessing, but did you declare your record and your ContentType in migration.cs? If you didn't, the content management will be unable to create a content item with your type as it will not know the type in question.
Your migration.cs should look somehow like that:
public class Migrations : DataMigrationImpl
{
public int Create()
{
SchemaBuilder.CreateTable("ProductRecord",
table =>
{
table.ContentPartRecord()
.Column<string>("Sku")
.Column<string>("Description")
.column<decimal>("Price");
});
ContentDefinitionManager.AlterTypeDefinition("Product", cfg => cfg.WithPart("ProductPart"));
return 1;
}
}
On a side note, the naming convention in Orchard is to name the record for a part XXXPartRecord. I don't think your problem lies there though.
I have mentioned this in you other thread.. Orchard Content Type is null
you need
Migrations
public class Migrations : DataMigrationImpl {
public int Create() {
SchemaBuilder.CreateTable("ProductRecord",
table => table
.ContentPartRecord()
.COLUMNS NEED TO BE SPECIFIED
);
ContentDefinitionManager.AlterTypeDefinition("Forum",
cfg => cfg
.WithPart("ProductPart")
.WithPart("CommonPart")
);
Repository
public class ProductPartHandler : ContentHandler {
public ProductPartHandler(IRepository repository) {
Filters.Add(StorageFilter.For(repository));
}
Hope this helps
You could try generating a similar part using the command line utility by pszmyd and see whats different.
http://www.szmyd.com.pl/blog/generating-orchard-content-parts-via-command-line