Using WCF Data Services 4.0, I cannot get the hierarchical data to return. I have a class Employee that has a collection of EquipmentIds. Those EquipmentIds are getting lost over the wire. Here's my code:
public class ODataV2 : DataService<ODataV2Model>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.UseVerboseErrors = true;
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
}
public class ODataV2Model
{
public ODataV2Model()
{
Employees = new List<Employee>{
new Employee { Id = 1, Name="Doug", EquipmentIds = new List<Equipment> { new Equipment { Id = 1 },new Equipment { Id = 2 } }.AsQueryable()},
new Employee { Id = 2, Name= "George", EquipmentIds = new List<Equipment> {new Equipment { Id = 3}, new Equipment { Id = 5} }.AsQueryable() }
}.AsQueryable();
}
public IQueryable<Employee> Employees { get; private set; }
public IQueryable<Equipment> EquipmentIds { get; private set; }
}
[DataServiceKey("Id")]
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public IQueryable<Equipment> EquipmentIds { get; set; }
}
[DataServiceKey("Id")]
public class Equipment
{
public int Id { get; set; }
}
When I run LinqPad on it, I get this:
I should have both collections of EquipmentIds with counts of 2, but I have 0. I don't receive an error, but the data never makes it to the client.
I switched to WCF Data Services v 5.0 and it works successfully on the .NET side, but I lose the ability to query with LinqPad. Is there a way for this to work in v 4.0?
If not, is there a way to upgrade LinqPad to recognize odata v3 (WCF Data Services 5.0)?
The query ~/Employees will only include the Employee entities and not any navigation property content. This is to reduce the payload size. If you really want to include some of the navigation properties just specify for example ~/Employees?$expand=EquipmentIds.
Related
I am using the new Azure.Data.Tables library from Microsoft to deal with Azure Table Storage. With the old library when you had an entity that implemented ITableEntity and you had a property that you did not want to save to the storage table you would use the [IgnoreProperty] annotation. However, this does not seem to be available on the new library.
What would be the equivalent on the Azure.Data.Tables package or how do you now avoid saving a property to table storage now?
This is the class I want to persist:
public class MySpatialEntity : ITableEntity
{
public int ObjectId { get; set; }
public string Name { get; set; }
public int MonitoringArea { get; set; }
//This is the property I want to ignore because table storage cannot store it
public Point Geometry { get; set; }
//ITableEntity Members
public virtual string PartitionKey { get => MonitoringArea.ToString(); set => MonitoringArea = int.Parse(value); }
public virtual string RowKey { get => ObjectId.ToString(); set => ObjectId = int.Parse(value); }
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
}
As of version 12.2.0.beta.1, Azure.Data.Tables table entity models now support ignoring properties during serialization via the [IgnoreDataMember] attribute and renaming properties via the [DataMember(Name="<yourNameHere>")] attribute.
See the changelog here.
I don't think there's anything like [IgnoreProperty] available as of now (at least with version 12.1.0).
I found two Github issues which talk about this:
https://github.com/Azure/azure-sdk-for-net/issues/19782
https://github.com/Azure/azure-sdk-for-net/issues/15383
What you can do is create a custom dictionary of the properties you want to persist in the entity and use that dictionary for add/update operations.
Please see sample code below:
using System;
using System.Collections.Generic;
using System.Drawing;
using Azure;
using Azure.Data.Tables;
namespace SO68633776
{
class Program
{
private static string connectionString = "connection-string";
private static string tableName = "table-name";
static void Main(string[] args)
{
MySpatialEntity mySpatialEntity = new MySpatialEntity()
{
ObjectId = 1,
Name = "Some Value",
MonitoringArea = 2
};
TableEntity entity = new TableEntity(mySpatialEntity.ToDictionary());
TableClient tableClient = new TableClient(connectionString, tableName);
var result = tableClient.AddEntity(entity);
}
}
public class MySpatialEntity: ITableEntity
{
public int ObjectId { get; set; }
public string Name { get; set; }
public int MonitoringArea { get; set; }
//This is the property I want to ignore because table storage cannot store it
public Point Geometry { get; set; }
//ITableEntity Members
public virtual string PartitionKey { get => MonitoringArea.ToString(); set => MonitoringArea = int.Parse(value); }
public virtual string RowKey { get => ObjectId.ToString(); set => ObjectId = int.Parse(value); }
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
public IDictionary<string, object> ToDictionary()
{
return new Dictionary<string, object>()
{
{"PartitionKey", PartitionKey},
{"RowKey", RowKey},
{"ObjectId", ObjectId},
{"Name", Name},
{"MonitoringArea", MonitoringArea}
};
}
}
}
Using a slightly modified version of the default ASP.NET MVC 5 template (with Individual Accounts), I am trying to get a subset of users based on an intermediary table. I have already built up an administration UI that can return a list of all users, but now I need to limit the set of users returned based on the currently logged in user's access privileges defined in the intermediary table.
Essentially, each user will have access to 1 or more clinics, so there will be one record for each clinic to which they have access.
If the currently logged in user belongs to a given role (e.g., "Clinic Admin"), then they should have the ability to retrieve a list of any users who belong to any of the clinics to which they have access.
Can anyone help point me in the right direction? This is my first Anything.NET application, so please feel free to explain like I'm five. :-)
Thank you in advance for any help you can offer.
Additional information:
Visual Studio 2013 Update 5
Entity Framework 6
MS SQL Server 2008 R2
Here is the intermediary table's class (ClinicUser):
[Table("clinic_users")]
public class ClinicUser
{
[Key]
public virtual ApplicationUser ApplicationUsers { get; set; }
[Required]
public string Id { get; set; }
[Required]
public System.Guid provider_id { get; set; }
[Required]
public System.Guid health_system_id { get; set; }
[Required]
public System.Guid clinic_id { get; set; }
}
Here is my ApplicationUser class:
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get { return FirstName + " " + LastName; }
}
[ForeignKey("ClinicUsers")]
public override string Id
{
get
{
return base.Id;
}
set
{
base.Id = value;
}
}
public virtual ClinicUser ClinicUsers { get; set; }
public IEnumerable<SelectListItem> RolesList { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
userIdentity.AddClaims(ClinicClaimsProvider.GetClaims(userIdentity));
return userIdentity;
}
}
In case it wasn't clear, what I'm really trying to do is narrow the list of ApplicationUsers to return only the list of users to which I have access to based on the clinics we have have in common.
If I were writing this as a SQL query, this would be one way to accomplish what I want (I just can't seem to quite get what I want with LINQ):
SELECT *
FROM AspNetUsers au
WHERE Id IN (
SELECT Id
FROM clinic_users
WHERE clinic_id IN (
SELECT clinic_id
FROM clinic_users
WHERE Id = 'CurrentUserId'
)
)
First of all do not user much properties in ApplicationUser class, you can manage user profiles table and connect it with application user class, so you can put lot of information about user in profile table.
Next task is organize table of clinics, branches etc... and asociate application users with them.
Next you have 2 ways:
1. asociate application users with clinics or branches.
or
2. Manage them with roles.
Here is example with Application users:
[Table("Clinics")]
public class Clinic
{
[Key]
public string Id { get; set; }
public virtual ICollection<ClinicUser> ClinicUsers { get; set; }
}
[Table("ClinicUsers")]
public class ClinicUser
{
[Key]
[Column(Order = 0)]
public string ClinicId { get; set; }
[Key]
[Column(Order = 1)]
public string UserId { get; set; }
}
So next you need Other ViewModels to display them hope this help.
UPDATE
// GET: ClinicUsers by Clinic
public async Task<ActionResult> ViewCurrentClinicUsers(string id) // This is clinis ID
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Clinic clinic = await db.clinic.FindAsync(id); // Get Selectedclinic
if (clinic == null)
{
return HttpNotFound();
}
ClinicUsers model = new ClinicUsers() // ClinicUsers model
{
clinic = clinic, // View Currentclinic
ClinicUsers = await db.ClinicUsers.Were(x => x.clinicid == clinic.id)ToListAsync()) // Get Users that asigned to current clinic
};
return View(model);
}
UPDATE 2
And Finaly if you want display clinics were is assigned current loged user
// GET: Clinics by currentuser
public async Task<ActionResult> ViewClinicsWithCurrentUserAccess()
{
var currentuserId = User.Identity.GetUserId(); // This gets currentloged user id
var currentuser = await db.Users.SingleOrDefaultAsync(x => x.Id == myUserId); // This gets currentloged user virtual
return View(await db.Clinics.Were(x => x.clinicuserid == currentuserId).ToListAsync());
}
I solved this a while back, but I thought I had better come back here and update my question with an answer, in case this might help someone else.
I updated my Clinic and ClinicUser classes accordingly:
Clinic.cs
[Table("clinics")]
public class Clinic
{
[Key]
public System.Guid ClinicId { get; set; }
public List<ClinicUser> ClinicUsers { get; set; }
}
ClinicUser.cs
[Table("clinic_users")]
public class ClinicUser
{
[Key, Column(Order = 0)]
public string UserId { get; set; }
[Key, Column(Order = 1)]
public System.Guid ClinicId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser ApplicationUser { get; set; }
[ForeignKey("ClinicId")]
public Clinic Clinic { get; set; }
}
Also, I updated the following excerpt of my ApplicationUser class from this:
[ForeignKey("ClinicUsers")]
public override string Id
{
get
{
return base.Id;
}
set
{
base.Id = value;
}
}
public virtual ClinicUser ClinicUsers { get; set; }
to this:
public List<ClinicUser> ClinicUsers { get; set; }
Finally, in my ApplicationUsersController's Index() action, I was able to use this:
public async Task<ActionResult> Index()
{
if (User.IsInRole("Admin")) return View(await UserManager.Users.ToListAsync());
var userId = User.Identity.GetUserId();
//Get the Ids of the current user's clinics
var userClinics = db.ClinicUsers.Where(cu => cu.UserId == userId).Select(cu => cu.ClinicId).ToList();
//Get all userIds of the user at the current user's clinics
var clinicUserIds = db.ClinicUsers.Where(cu => userClinics.Contains(cu.ClinicId)).ToList().Select(cu => cu.UserId);
var users = UserManager.Users.Where(u => clinicUserIds.Contains(u.Id));
return View(await users.ToListAsync());
}
In essence, if the user has the "Admin" role, then they will get a list of all users in the database. If they aren't, they will only get a list of the users that also belong to the clinics they have in common.
It may not be perfect, but it works. If anyone has any suggestions on how to improve this, I would be glad to hear it.
Again, my thanks to Archil (https://stackoverflow.com/users/4089212/archil-labadze) for his helpful responses.
I have this Party class which contains an object data type coming from a service. It can contain two different member types for the Item property.
public class Party
{
public string DMVID {get; set;}
public object Item { get; set; }
}
and this DTO
public class PartyDTO
{
public string DMVID {get; set;}
public BusinessDTO BusinessItem { get; set; }
public IndividualDTO IndividualItem { get; set; }
}
How can I map the output of the Item to BusinessItem or IndividualItem.
I know this one would not work. Mapper.CreateMap<Party, PartyDTO>();
I don't know if conditional mapping can solve this or a resolver like this one.
Hey maybe this will help you out! I tested it, but i am using AutoMapper just for two days!
Allright here are your noted classes!!!
public class Party
{
public string DMVID { get; set; }
public object Item { get; set; }
}
public class PartyDTO
{
public string DMVID { get; set; }
public BuisnessDTO BusinessItem { get; set; }
public IndividualDTO IndividualItem { get; set; }
}
public class BuisnessDTO
{
public int Number
{
get;
set;
}
}
public class IndividualDTO
{
public string Message
{
get;
set;
}
}
and here your is the MapperConfiguration for this current scenario!
// Edit There was no need here for some conditions
AutoMapper.Mapper.CreateMap<Party, PartyDTO>()
.ForMember(dto => dto.BusinessItem, map =>
map.MapFrom(party => party.Item as BuisnessDTO);
)
.ForMember(dto => dto.IndividualItem, map =>
map.MapFrom(party => party.Item as IndividualDTO);
);
// And this is another way to achive the mapping in this scenario
AutoMapper.Mapper.CreateMap<PartyDTO, Party>()
.ForMember(party => party.Item, map => map.MapFrom( dto => (dto.BusinessItem != null) ? (dto.BusinessItem as object) : (dto.IndividualItem as object)));
And i created this sample for it!
Party firstParty = new Party()
{
DMVID = "something",
Item = new BuisnessDTO()
{
Number = 1
}
};
Party secondParty = new Party()
{
DMVID = "something",
Item = new IndividualDTO()
{
Message = "message"
}
};
PartyDTO dtoWithBuisness = AutoMapper.Mapper.Map<PartyDTO>(firstParty);
PartyDTO dtoWithIndividual = AutoMapper.Mapper.Map < PartyDTO>(secondParty);
Party afterParty = AutoMapper.Mapper.Map<Party>(dtoWithBuisness);
afterParty = AutoMapper.Mapper.Map < Party>(dtoWithIndividual);
Of course there are other possibility, but I think thats exactly what you wanted.
I am intending to insert/delete some information in a module's Action (using Orchard Rules-Action API) in a one-column table in the database. What is the best way of doing such tasks i.e. Data manipulation of non-content items. I do not want to go by the "Create a content type" route. I simply want to persist some non-content data in the database and query/delete them.
namespace xyz.Models
{
public class Task
{
public virtual int ContentId { get; set; }
public virtual int Retries { get; set; }
}
}
SchemaBuilder.CreateTable("Task",
table => table
.Column<int>("ContentId")
.Column<int>("Retries")
);
return 1;
namespace Xyz.Services
{
public class TaskService : ITaskService
{
private readonly IRepository<Task> _taskRepository;
public TaskService(IRepository<Task> taskRepository)
{
_taskRepository = taskRepository;
}
public Task CreateTask(int contentId)
{
var task = new Task { ContentId = contentId };
_taskRepository.Create(task);
return task;
}
}
}
If you mean "creating a table without ContentPart" by non-content, then just create your desired model in the models folder :
public class MyRecord{
public virtual int Id { get; set; }
public virtual string FOO{ get; set; }
public virtual string BAR{ get; set; }
}
and obviously you must create a table in migration as following :
SchemaBuilder.CreateTable("MyRecord",
table => table
.Column<int>("Id", c => c.PrimaryKey().Identity())
.Column<string>("FOO")
.Column<string>("BAR")
);
and finally where you want to have a transaction over table ,simply inject an instance of your model's repository :
private readonly IRepository<MyRecord> _repository;
public SomeClass(IRepository<MyRecord> repository){
_repository = repository;
}
public SomeMethod(){
var record = new MyRecord();
//initialize your class here
_repository.Create(record);
}
Important to note is that your record class must be in the Models folder and must contain an Id property.
I am using C# .NET 4.0 and Newtonsoft JSON 4.5.0.11
[JsonObject(MemberSerialization.OptIn)]
public interface IProduct
{
[JsonProperty(PropertyName = "ProductId")]
int Id { get; set; }
[JsonProperty]
string Name { get; set; }
}
public abstract class BaseEntity<T>
{
private object _id;
public T Id
{
get { return (T)_id; }
set { _id = value; }
}
}
public class Product : BaseEntity<int>, IProduct
{
public string Name { get; set; }
public int Quantity { get; set; }
}
I need to serialize part of object and I use interfaces with declared concrete properties to do this.
The serialization looks like:
Product product = new Product { Id = 1, Name = "My Product", Quantity = 5};
JsonConvert.SerializeObject(product);
Expected result is:
{"ProductId": 1, "Name": "My Product"}
But actual result is:
{"Name": "My Product"}
How can I serialize this object correctly?
UPD: Looked at the source code of json.net and came to the conclusion that this is a bug with grab information about object through ReflectionUtils.
Have you tried this?
public interface IProduct
{
int Id { get; set; }
string Name { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public abstract class BaseEntity<T>
{
private object _id;
[JsonProperty]
public T Id
{
get { return (T)_id; }
set { _id = value; }
}
}
[JsonObject(MemberSerialization.OptIn)]
public class Product : BaseEntity<int>, IProduct
{
[JsonProperty]
public string Name { get; set; }
[JsonProperty]
public int Quantity { get; set; }
}