WCF DATA SERVICES AddObject - wcf

I am trying to add an object to my entity but it is giving me the error: "Not Found"
here is my code:
DataServiceContext dtx = new DataServiceContext(new Uri("http://localhost/website2/wcfservice1.svc/"));
dtx.Credentials = System.Net.CredentialCache.DefaultCredentials;
ServiceReference1.Car car = new ServiceReference1.Car();
car.CarName = "aaa";
car.CarModel = "111";
dtx.AddObject("Car", car);
dtx.SaveChanges();
I have tried "Cars" and "Car" both in AddObject but still didnt help.. my CARID column is a PKEY column in database.
Please help. Thanks.

You may need to set the read/write settings on your DataService class
public class FooDataService : DataService<MyContext>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Cars", EntitySetRights.All);
}
}
If you are using an ObjectContext then DataService<T> will know to use the EF WCF Data Services Provider. However if your T is anything but, (for example DbContext or DataContext), then by default WCF Data Services uses the reflection provider (which is readonly).
There is a hack to get the ObjectContext out of a DbContext, but if you need to use DataContext, nHibernate, or any other type of context, you will need to write a custom IDataServiceUpdateProviderimplementation.

Related

Unable to resolve service for type 'System.String' while attempting to activate in .net core

I have a factory class and it has a constructor where dependency injection is implemented. When trying to register the factory method in program.cs file I get the below error when running the application. "Unable to resolve service for type 'System.String' while attempting to activate 'Factory".
public class Factory : IFactory
{
private readonly A _a;
private readonly string _test;
public Factory(A a, string sample)
{
_a= a;
_test= string.IsNullOrEmpty(sample) ? string.Empty : Path.GetFullPath(sample);
}
private string Create(long id)
{
var b = _test.make(id);
return b;
}
}
In program.cs file how can we register this string element _test? Can anyone help!
It is because your Factory constructor is not parameter-less, and when the service provider tries to instantiate the Factory, it has no value to pass for the "sample" variable.
There are two possible solutions to this:
1- Changing the design of your factory, and passing the "sample" as a variable to Create method instead of the constructor.
OR
2- Registering the factory like this:
services.AddSingleton(s => new Factory(s.GetService<A>(), "desired string"));
Btw, I don't know what is the use case that you have for implementing this factory class, but it doesn't seem the right way of implementing it. I suggest you take a look at this beforehand:
Factory Design Pattern

How to keep separate membership filter annotation in MVC 4 project

My solution architecture is as follow:
MVC 4 - presentation layer
Manager class library
DAL library
common DTO project library.
Now, I have added simple membership related classes and implemented.
Here, Problem is - InitializeSimpleMembership filter is existed into MVC 4 project and it contains - DBCONTEXT object... which is wrong as DBCONTEXT object or any DAL reference should not be exist into MVC 4 and I want to keep these separate into DAL project only.
Below is the filter code:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<FinalEFFirstContext>(null);
try
{
using (var context = new FinalEFFirstContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
if (!WebSecurity.Initialized)
{
WebSecurity.InitializeDatabaseConnection("FinalEFFirstContext", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
if (!WebSecurity.ConfirmAccount("admin#mydom.com") && !WebSecurity.UserExists("admin#mydom.com"))
{
WebSecurity.CreateUserAndAccount("admin#mydom.com", "password");
}
if (!Roles.RoleExists("Administrator"))
{
Roles.CreateRole("Administrator");
Roles.AddUserToRole("admin#mydom.com", "Administrator");
}
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
Please guide me how I could separate this filter ?
Do I have to move this class into Manager class library and add these all MVC reference there ?
Thank You
Yes, you can consider moving the InitializeSimpleMembershipAttribute into your DAL layer (where you context class reside).
IMO it is fine to have a reference to DAL into your web project as long as you are depending on abstraction to access persistent store. For example, I derive my data context from IDataContext. The current datacontext which implement IDataContext interface uses EF as ORM. But tomorrow if we choose to switch to another ORM say NHibernate, all we need to do is implement IDataContext and change the dependency to resolve to new DataContext.
So you are right web project should not know how and from where we are accessing the data. That can be achieved by not giving a reference to EntityFramwork in web project. DAL reference is fine as long as web project does not get affected if you choose to change your ORM or data access technologies.
I can show you my solution structure which shows not reference to EF and filter in DAL, if it helps you:

EntityFramework.dll DbContext conflicting with Microsoft.data.Entity.CTP DbContext

Grabbed this from a sample:
protected override ObjectContext CreateDataSource()
{
NorthwindContext nw = new NorthwindContext();
// Configure DbContext before we provide it to the
// data services runtime.
nw.Configuration.ValidateOnSaveEnabled = false;
// Get the underlying ObjectContext for the DbContext.
var context = ((IObjectContextAdapter)nw).ObjectContext;
// Return the underlying context.
return context;
}
Modified it to use the DbContext class that I have in my project.
EDIT: Clarifying that I am casting from a DbContext class just as the sample does:
public class NorthwindContext : DbContext
{
// Use the constructor to target a specific named connection string
public NorthwindContext()
: base("name=NorthwindEntities")
{
// Disable proxy creation as this messes up the data service.
this.Configuration.ProxyCreationEnabled = false;
// Create Northwind if it doesn't already exist.
this.Database.CreateIfNotExists();
}
Running the code gives me an error on the line casting the DbContext:
Unable to cast object of type 'MyProject.MyDbContext' to type 'System.Data.Entity.Infrastructure.IObjectContextAdapter'.
Despite the fact that DbContext implements IObjectContextAdapter:
public class DbContext : IDisposable, IObjectContextAdapter
I've found several questions here on SO and other googled sources, but no solutions I have found work.
I'm using Entity Framework 4.2, attempted to update to the 4.3 beta and I'm not sure if that stuck.
Overall goal is to serve data in WCF as a DataService.
Update: Digging deeper I find that there is an ambiguity issue between what my DbContext was (From EntityFramework.dll ) and the type in the WCF project (from Microsoft.data.Entity.CTP)
Not sure how to get what I want from both here....
Just a reminder, the issue here was that an ambiguity between EntityFramework.dll and Microsoft.Data.Entity.CTP was causing the DataInitializer I had for my DbContext to lose functionality.
I solved this issue by replacing my Initializer here:
public class MyDataInitializer : RecreateDatabaseIfModelChanges<MyData>
{
public void Seed(MyData context)
To:
public class MyDataInitializer : IDatabaseInitializer<MyData>
{
public void InitializeDatabase(MyData context)
And I can now access my DataService.
Just one

Passing an Entity Framework Context object to WCF

I need to pass a Context object from EF into a WCF method.
Normally, I create the Context object in the WCF method and dispose of it right before the end of the method call which works just fine for most of my methods.
However, I need to pass the Context object (specifically the DBContext) over from the MVC controller to my specific WCF method because I have caching enabled for some lookup tables. I need this specific Context object passed over (the one I set in the Application_Start method of the Global.asax file) rather than what I do in the sentence above because I use this specific object for the SqlDependency. If I try and create the DBContext object brand new, I can't use the SqlDependency becuase I will get an error informing me that the SqlDependency needs to be enabled before the database call.
The problem is that I'm getting the following error (shortened for brevity) when I try and start my WCF Test Client tool which I know has something to do with not properly declaring a KnownType attribute (ie the DBContext object). Note that the WCF project compiles just fine. I need some help with this specific part since I have never used a KnownType in my WCF service. They have all been simple types (int, string, etc).
Error: Cannot obtain Metadata from http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/mex
If this is a Windows (R) Communication Foundation service to which you
have access, please check that you have enabled metadata publishing at
the specified address. For help enabling metadata publishing, please
refer to the MSDN documentation at
http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange
Error URI:
http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/mex
Metadata contains a reference that cannot be resolved:
I have the following OperationContract code in my WCF service:
[OperationContract]
IEnumerable<Category> GetCategories(YeagerTechEntities DbContext);
I have the following DataContract code in my WCF service:
namespace YeagerTechModel
{
[Serializable]
[DataContract(IsReference = true)]
[KnownType(typeof(YeagerTechEntities))]
public partial class Category
{
public Category()
{
this.Projects = new HashSet<Project>();
}
[DataMember]
public short CategoryID { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public virtual ICollection<Project> Projects { get; set; }
}
}
Finally, the following is my WCF method:
public IEnumerable<YeagerTechModel.Category> GetCategories(YeagerTechEntities DbContext)
{
//YeagerTechEntities DbContext = new YeagerTechEntities();
DbContext.Configuration.ProxyCreationEnabled = false;
IEnumerable<YeagerTechModel.Category> category = DbContext.Categories.Where(p => p.CategoryID > 0).AsCached("Categories").ToList();
//IEnumerable<YeagerTechModel.Category> category = DbContext.Categories.Where(p => p.CategoryID > 0);
CloseConnection(DbContext);
return category;
}
You need singleton object following registry / service locator pattern. This object will hold reference to your global objects. For example at application start you will fill this object with your context using SqlDependency and you will use the registry to access this context in your controller's actions and service's operations.
Anyway work with this very carefully. SqlDependency and EF doesn't play nice together because it will make your context long living. Long living context is in most cases anti-pattern. Never ever use that context for anything else then loading cached data. Don't use it for data modification or loading non cached relations! Load entities as non-tracked (AsNoTracking extension method on query) in the first query and turn off proxy creation and lazy loading for that context.
Also be aware that query in EF is always executed in the database. I'm not sure what your AsCached is supposed to do but I somehow doubt it will work. What you need is probably:
var category = DbContext.Categories.Local
.Where(p => p.CategoryID > 0)
.ToList();
I would not use SqlDependency with EF. I would use ADO.NET and SQL directly. For caching in EF I would check EF Caching provider to use second level cache which is in most cases enough.

oData WCF service - hide an element

I'm new to WCF. My web project has an ADO.NET Entity Data Model (aka EF edmx), which has the Entity Container Name JobSystemEntities.
I've created a simple oData WCF data service which uses JobSystemEntities, and it works great:
public class JobService : DataService<JobSystemEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Jobs", EntitySetRights.ReadSingle);
}
However, this exposes all of the properties on the Job. I would like to hide sensitive data, i.e. the Cost field/property/column of the Job table.
I am posting this a but late, but it might help others.
You can use the IgnoreProperties attribute http://msdn.microsoft.com/en-us/library/system.data.services.ignorepropertiesattribute.aspx on your class.
You will have to define a partial Job class in order to do this. Something in the lines of:
namespace DAL.Entities
{
[IgnoreProperties("Cost")]
public partial class Job
{
}
}
I've done something similar to this. A good starting point is found here:
http://weblogs.asp.net/rajbk/archive/2010/05/15/pre-filtering-and-shaping-odata-feeds-using-wcf-data-services-and-the-entity-framework-part-1.aspx
Basically you will need to separate the protected properties of an entity into a separate entity that is linked as a property of the other. Once that is done user a Query Interceptor to restrict when that protected entity can be viewed.
[QueryInterceptor("YourObjectsProtectedProperties")]
public Expression<Func<YourObjectsProtectedProperties, bool>> OnReadYourObjectsProtectedProperties()
{
if (ShowEntityToUser())
return o => true == true;
return o => true == false;
}