Consume WSDL proxy class using c# - wcf

I have generated a proxy class but I don't know how to consume it.
I also instantiated the class and accessed the class but I don't know how to get the response
My Access code
Controller class to access the proxy :
ProjectByElementsQuerySelectionByElements query = new
ProjectByElementsQuerySelectionByElements();
ProjectByElementsQueryMessage_sync sync = new ProjectByElementsQueryMessage_sync{
ProjectSelectionByElements = query
};
Proxy Soap class :
This is the automatically generated from wsdl file and is a proxy class that I want to consume.
public partial class ProjectStatusByQueryResponse {
private ProjectLifeCycleStatusCode projectLifeCycleStatusCodeField;
private UPTODATEOUTOFDATE_UpToDatenessStatusCode schedulingUpToDatenessStatusCodeField;
private StartingStatusCode startingStatusCodeField;
private ProjectTaskLifeCycleStatusCode taskLifeCycleStatusCodeField;
private BlockingStatusCode taskBlockingStatusCodeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ProjectLifeCycleStatusCode ProjectLifeCycleStatusCode {
get {
return this.projectLifeCycleStatusCodeField;
}
set {
this.projectLifeCycleStatusCodeField = value;
}
}
public partial class ProjectByElementsQuerySelectionByElements {
private ProjectSelectionByResponsibleUnitID[] selectionByResponsibleUnitIDField;
private ProjectSelectionByProjectId[] selectionByProjectIDField;
private ProjectSelectionByProjectName[] selectionByProjectNameField;
private ProjectSelectionByProjectType[] selectionByProjectTypeField;
private ProjectSelectionByCustomerID[] selectionByCustomerIDField;
private ProjectSelectionByRequestingUnitID[] selectionByRequestingUnitIDField;
private bool selectionByBillableIndicatorField;
private bool selectionByBillableIndicatorFieldSpecified;
private ProjectSelectionByInterCompanyIndicator[] selectionByIntercompanyIndicatorField;
private ProjectSelectionByResponsibleEmployeeID[] selectionByResponsibleEmployeeIDField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SelectionByResponsibleUnitID", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ProjectSelectionByResponsibleUnitID[] SelectionByResponsibleUnitID {
get {
return this.selectionByResponsibleUnitIDField;
}
set {
this.selectionByResponsibleUnitIDField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SelectionByProjectID", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ProjectSelectionByProjectId[] SelectionByProjectID {
get {
return this.selectionByProjectIDField;
}
set {
this.selectionByProjectIDField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SelectionByProjectName", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ProjectSelectionByProjectName[] SelectionByProjectName {
get {
return this.selectionByProjectNameField;
}
set {
this.selectionByProjectNameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SelectionByProjectType", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ProjectSelectionByProjectType[] SelectionByProjectType {
get {
return this.selectionByProjectTypeField;
}
set {
this.selectionByProjectTypeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SelectionByCustomerID", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ProjectSelectionByCustomerID[] SelectionByCustomerID {
get {
return this.selectionByCustomerIDField;
}
set {
this.selectionByCustomerIDField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SelectionByRequestingUnitID", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ProjectSelectionByRequestingUnitID[] SelectionByRequestingUnitID {
get {
return this.selectionByRequestingUnitIDField;
}
set {
this.selectionByRequestingUnitIDField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public bool SelectionByBillableIndicator {
get {
return this.selectionByBillableIndicatorField;
}
set {
this.selectionByBillableIndicatorField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool SelectionByBillableIndicatorSpecified {
get {
return this.selectionByBillableIndicatorFieldSpecified;
}
set {
this.selectionByBillableIndicatorFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SelectionByIntercompanyIndicator", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ProjectSelectionByInterCompanyIndicator[] SelectionByIntercompanyIndicator {
get {
return this.selectionByIntercompanyIndicatorField;
}
set {
this.selectionByIntercompanyIndicatorField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("SelectionByResponsibleEmployeeID", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public ProjectSelectionByResponsibleEmployeeID[] SelectionByResponsibleEmployeeID {
get {
return this.selectionByResponsibleEmployeeIDField;
}
set {
this.selectionByResponsibleEmployeeIDField = value;
}
}
}

The proxy class file is added to the project to instantiate the proxy class to call the wcf service. If you don’t understand how to call the wcf service in this way, you can refer to ServiceModel Metadata Utility Tool.
In addition, you can also call the wcf service by adding a service reference. This is the simplest way. Right-click the project and select addservicereference in add, and then add the service reference.

Related

Unable to read FaultException from an asp.net core connected service

I'm trying to catch the FaultException on a WCF client.
the generated reference contract is:
[System.ServiceModel.OperationContractAttribute(Action="urn:wcfname#method", ReplyAction="*")]
[System.ServiceModel.FaultContractAttribute(typeof(Error[]), Action= "urn:wcfname#method", Name="errors")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(Response))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(Request))]
service.response method(service.request request);
and the generated error class is:
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.2")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="wcf")]
public partial class Error
{
private string errorCodeField;
private string errorStringField;
private string subErrorCodeField;
private string offendingFieldField;
private System.DateTime timeStampField;
private bool timeStampFieldSpecified;
private string detailStringField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="integer", Order=0)]
public string errorCode
{
get
{
return this.errorCodeField;
}
set
{
this.errorCodeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=1)]
public string errorString
{
get
{
return this.errorStringField;
}
set
{
this.errorStringField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="integer", Order=2)]
public string subErrorCode
{
get
{
return this.subErrorCodeField;
}
set
{
this.subErrorCodeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string offendingField
{
get
{
return this.offendingFieldField;
}
set
{
this.offendingFieldField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=4)]
public System.DateTime timeStamp
{
get
{
return this.timeStampField;
}
set
{
this.timeStampField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool timeStampSpecified
{
get
{
return this.timeStampFieldSpecified;
}
set
{
this.timeStampFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=5)]
public string detailString
{
get
{
return this.detailStringField;
}
set
{
this.detailStringField = value;
}
}
}
the code to call the sercie is below:
try
{
//call the service method
}
catch (FaultException<Error[]> ex)
{
var errorElement = XElement.Parse(ex.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml());
var xmlDetail = (string)errorElement;
}
catch (FaultException ex)
{
var errorElement = XElement.Parse(ex.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml());
var xmlDetail = (string)errorElement;
}
When theres a FaultExeption<Error[]> ex, it enters there, but the error is empty string.
If I comment that part, it enters on the FaultException ex, but again the error is empty string.
I'm using .netCore 3.1
Any advice is appreciated.
Throwing FaultException indicates that there is no problem with the channel. The exception was thrown by the service. WCF's FaultException message is too general to pinpoint a specific problem, so you can customize the exception message like this:
public class HomeService : IHomeService
{
public Student Get(string id)
{
try
{
//Here, of course, an exception will be thrown
var result = Convert.ToInt32(id) / Convert.ToInt32("0");
return new Student() { ID = Convert.ToInt32(id), Name = "hxc", SNS = "001" };
}
catch (Exception ex)
{
var reason = new FaultReason("Exception thrown information");
var code = new FaultCode("500");
var faultException = new FaultException(reason, code, "It is GET that throws the exception");
throw faultException;
}
}
}

How to use operation inside proxy class as sync only?

I followed article to include WCF service into my ASP.NET core application.
It seems that Generated Reference.cs file automatically included Async operations. Is it possible to make these operation sync only? Either in Reference.cs using them on client side.?
Generated Reference.cs file looks like follows-
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// //
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SimpleServiceReference
{
using System.Runtime.Serialization;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.5.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="CompositeType", Namespace="http://schemas.datacontract.org/2004/07/SimpleService")]
public partial class CompositeType : object
{
private bool BoolValueField;
private string StringValueField;
[System.Runtime.Serialization.DataMemberAttribute()]
public bool BoolValue
{
get
{
return this.BoolValueField;
}
set
{
this.BoolValueField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public string StringValue
{
get
{
return this.StringValueField;
}
set
{
this.StringValueField = value;
}
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.5.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="SimpleServiceReference.ISimpleService")]
public interface ISimpleService
{
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISimpleService/GetData", ReplyAction="http://tempuri.org/ISimpleService/GetDataResponse")]
System.Threading.Tasks.Task<string> GetDataAsync(int value);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISimpleService/GetDataUsingDataContract", ReplyAction="http://tempuri.org/ISimpleService/GetDataUsingDataContractResponse")]
System.Threading.Tasks.Task<SimpleServiceReference.CompositeType> GetDataUsingDataContractAsync(SimpleServiceReference.CompositeType composite);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.5.0.0")]
public interface ISimpleServiceChannel : SimpleServiceReference.ISimpleService, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.5.0.0")]
public partial class SimpleServiceClient : System.ServiceModel.ClientBase<SimpleServiceReference.ISimpleService>, SimpleServiceReference.ISimpleService
{
/// <summary>
/// Implement this partial method to configure the service endpoint.
/// </summary>
/// <param name="serviceEndpoint">The endpoint to configure</param>
/// <param name="clientCredentials">The client credentials</param>
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
public SimpleServiceClient() :
base(SimpleServiceClient.GetDefaultBinding(), SimpleServiceClient.GetDefaultEndpointAddress())
{
this.Endpoint.Name = EndpointConfiguration.BasicHttpBinding_ISimpleService.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}
public SimpleServiceClient(EndpointConfiguration endpointConfiguration) :
base(SimpleServiceClient.GetBindingForEndpoint(endpointConfiguration), SimpleServiceClient.GetEndpointAddress(endpointConfiguration))
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}
public SimpleServiceClient(EndpointConfiguration endpointConfiguration, string remoteAddress) :
base(SimpleServiceClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}
public SimpleServiceClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) :
base(SimpleServiceClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}
public SimpleServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public System.Threading.Tasks.Task<string> GetDataAsync(int value)
{
return base.Channel.GetDataAsync(value);
}
public System.Threading.Tasks.Task<SimpleServiceReference.CompositeType> GetDataUsingDataContractAsync(SimpleServiceReference.CompositeType composite)
{
return base.Channel.GetDataUsingDataContractAsync(composite);
}
public virtual System.Threading.Tasks.Task OpenAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
}
public virtual System.Threading.Tasks.Task CloseAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
}
private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_ISimpleService))
{
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.MaxBufferSize = int.MaxValue;
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
result.MaxReceivedMessageSize = int.MaxValue;
result.AllowCookies = true;
return result;
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}
private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_ISimpleService))
{
return new System.ServiceModel.EndpointAddress("http://localhost:49945/SimpleService.svc");
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}
private static System.ServiceModel.Channels.Binding GetDefaultBinding()
{
return SimpleServiceClient.GetBindingForEndpoint(EndpointConfiguration.BasicHttpBinding_ISimpleService);
}
private static System.ServiceModel.EndpointAddress GetDefaultEndpointAddress()
{
return SimpleServiceClient.GetEndpointAddress(EndpointConfiguration.BasicHttpBinding_ISimpleService);
}
public enum EndpointConfiguration
{
BasicHttpBinding_ISimpleService,
}
}
}
You can call async method synchronously and there are several ways to do this:
For Task<T> use:
var result = Task.Run(AsyncMethod).Result;
// if the Task fails, GetResult() will just throw an `AggregateException`
// or use
var result AsyncMethod.GetAwaiter().GetResult();
// if the Task fails, GetResult() will just throw the exception caused directly
For Task (not Task<T>) use:
AsyncMethod.RunSynchronously();

SimpleIoC - Type not found in cache: Windows.UI.Xaml.Controls.Frame

I am running into the below error the first time my ViewModel is being instantiated by the SimpleIoC. I believe I have setup the container as it should be, but for some reason, I am still getting the below error. Any ideas or assistance would be very much appreciated.
Microsoft.Practices.ServiceLocation.ActivationException was unhandled by user code
HResult=-2146233088
Message=Type not found in cache: Windows.UI.Xaml.Controls.Frame.
Source=GalaSoft.MvvmLight.Extras
StackTrace:
at GalaSoft.MvvmLight.Ioc.SimpleIoc.DoGetService(Type serviceType, String key) in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 532
at GalaSoft.MvvmLight.Ioc.SimpleIoc.GetService(Type serviceType) in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 768
at GalaSoft.MvvmLight.Ioc.SimpleIoc.MakeInstance[TClass]() in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 708
InnerException:
Here are pieces of my code related to this:
ViewModelLocator.cs (Located in my Win8 project)
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
// Create design time view services and models
//SimpleIoc.Default.Register<IDataService, DesignDataService>();
}
else
{
// Create run time view services and models
//SimpleIoc.Default.Register<IDataService, DataService>();
SimpleIoc.Default.Register<INavigationService, NavigationService>();
SimpleIoc.Default.Register<IParseService, ParseService>();
SimpleIoc.Default.Register<IServiceHandler, ServiceHandler>();
}
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<ActionViewModel>();
}
public MainViewModel MainVM
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public ActionViewModel ActionVM
{
get
{
return ServiceLocator.Current.GetInstance<ActionViewModel>();
}
}
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
MainViewModel.cs Constructor
public class MainViewModel : ViewModelBase
{
#region Variables
private readonly INavigationService _navigationService;
private readonly IParseService _parseService;
#endregion
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel(INavigationService navigationService, IParseService parseService)
{
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
_navigationService = navigationService;
_parseService = parseService;
BuildCommonData();
}
}
I know this is long overdue, but here is the offending code in the implementation of my NavigationService class.
NavigationService class (Before)
public class NavigationService : INavigationService
{
/// <summary>
/// Gets the root frame.
/// </summary>
private Frame RootFrame;
public NavigationService(Frame rootFrame)
{
RootFrame = rootFrame;
}
public event NavigatingCancelEventHandler Navigating;
public void Navigate<T>(object parameter = null)
{
var type = typeof(T);
RootFrame.Navigate(type, parameter);
}
public void Navigate(string type, object parameter = null)
{
RootFrame.Navigate(Type.GetType(type), parameter);
}
public void GoBack()
{
if (RootFrame.CanGoBack)
{
RootFrame.GoBack();
}
}
public void GoForward()
{
if (RootFrame.CanGoForward)
{
RootFrame.GoForward();
}
}
}
I simply took out the constructor, and made the RootFrame private variable a property. Like so:
public class NavigationService : INavigationService
{
/// <summary>
/// Gets the root frame.
/// </summary>
private static Frame RootFrame
{
get { return Window.Current.Content as Frame; }
}
public event NavigatingCancelEventHandler Navigating;
public void Navigate<T>(object parameter = null)
{
var type = typeof(T);
RootFrame.Navigate(type, parameter);
}
public void Navigate(string type, object parameter = null)
{
RootFrame.Navigate(Type.GetType(type), parameter);
}
public void GoBack()
{
if (RootFrame.CanGoBack)
{
RootFrame.GoBack();
}
}
public void GoForward()
{
if (RootFrame.CanGoForward)
{
RootFrame.GoForward();
}
}
}
Simple, I know, but hope it's of some use.
I was getting the same error today in my Xamarin project. The actual error given was "System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'" and then when I look up the InnerException I could see the actual error, which is Type not found in cache.
It was a silly mistake that I was using DataService instead of IDataService for the Constructor Dependency Injection.
public SearchViewModel(DataService dataService, IErrorLoggingService errorLoggingService, IDialogService dialogService, IResourceService resourceService, INavigationService navigationService) {
SearchCommand = new AsyncRelayCommand <SearchFilter>(SearchAsync);
DataService = dataService;
ErrorLoggingService = errorLoggingService;
DialogService = dialogService;
ResourceService = resourceService;
NavigationService = navigationService;
CancelCommand = new RelayCommand(Cancel);
}
And just for your information, this is how I registered my service.
SimpleIoc.Default.Register<IDataService, DataService>();
So the issue was fixed after changing to IDataService. Hope it helps.

How to make queries to a WCF service with EF model / data first

I have a client project and a MVC3 EF model first project that exposes a WCF service to the client. I am new to EF and some things are not so clear.
Lets assume the Northwind service with Product entity, if i want to make a simple query like return the products with a specific price, where do i write the code for the query ?
On the server side there is only EDM and the service itself and it is pretty straighforward, hardly any code there.
On the client i have Product model class and NorthwindContext and also a ProdcutsPageViewModel class (it's a MVVM project)
So my question is, How and where do i make queries to the DB ? do i make it from the client side by attaching LINQ code to the URI ? do i make it from the server side by adding new methods to the service ? I would appreciate if you could explain it to a newbie,
Thanks !
Here is some of the code :
On the server, the NorthwindODataService service class:
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class NorthwindODataService : DataService<NorthwindEntities>
{
private readonly IUserPrivilegesRepository userPrivilegesRepository;
private readonly IClaimsIdentity identity;
public NorthwindODataService()
: this(HttpContext.Current.User.Identity as IClaimsIdentity, new InfrastructureEntities())
{
}
public NorthwindODataService(IClaimsIdentity identity, IUserPrivilegesRepository userPrivilegesRepository)
{
this.identity = identity;
this.userPrivilegesRepository = userPrivilegesRepository;
}
protected string UserId
{
get
{
var nameIdentifierClaim = this.identity.Claims.SingleOrDefault(c => c.ClaimType == ClaimTypes.NameIdentifier);
if (nameIdentifierClaim == null)
{
throw new DataServiceException(401, "Unauthorized", "The request requires authentication.", "en-US", null);
}
return nameIdentifierClaim.Value;
}
}
/// <summary>
/// Initializes service-wide policies. This method is called only once.
/// </summary>
/// <param name="config"></param>
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Products", EntitySetRights.All);
config.SetEntitySetAccessRule("Categories", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("Suppliers", EntitySetRights.AllRead);
config.SetEntitySetPageSize("Products", 20);
config.SetEntitySetPageSize("Categories", 20);
config.SetEntitySetPageSize("Suppliers", 20);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
config.UseVerboseErrors = true;
}
/// <summary>
/// Define a query interceptor for the Products entity set.
/// </summary>
/// <returns></returns>
[QueryInterceptor("Products")]
public Expression<Func<Product, bool>> OnQueryProducts()
{
this.ValidateAuthorization("Products", PrivilegeConstants.SqlReadPrivilege);
// The user has Read permission.
return p => true;
}
/// <summary>
/// Define a query interceptor for the Categories entity set.
/// </summary>
/// <returns></returns>
[QueryInterceptor("Categories")]
public Expression<Func<Category, bool>> OnQueryCategories()
{
this.ValidateAuthorization("Categories", PrivilegeConstants.SqlReadPrivilege);
// The user has Read permission.
return p => true;
}
/// <summary>
/// Define a query interceptor for the Suppliers entity set.
/// </summary>
/// <returns></returns>
[QueryInterceptor("Suppliers")]
public Expression<Func<Supplier, bool>> OnQuerySuppliers()
{
this.ValidateAuthorization("Suppliers", PrivilegeConstants.SqlReadPrivilege);
// The user has Read permission.
return p => true;
}
/// <summary>
/// Define a change interceptor for the Products entity set.
/// </summary>
/// <param name="product"></param>
/// <param name="operations"></param>
[ChangeInterceptor("Products")]
public void OnChangeProducts(Product product, UpdateOperations operations)
{
if (operations == UpdateOperations.Change)
{
this.ValidateAuthorization("Products", PrivilegeConstants.SqlUpdatePrivilege);
var entry = default(ObjectStateEntry);
if (this.CurrentDataSource.ObjectStateManager.TryGetObjectStateEntry(product, out entry))
{
// Reject changes to a discontinued Product.
// Because the update is already made to the entity by the time the
// change interceptor in invoked, check the original value of the Discontinued
// property in the state entry and reject the change if 'true'.
if ((bool)entry.OriginalValues["Discontinued"])
{
throw new DataServiceException(400, "Bad Request", "A discontinued product cannot be modified.", "en-US", null);
}
}
else
{
throw new DataServiceException(404, "Not Found", "The requested product could not be found in the data source.", "en-US", null);
}
}
else if (operations == UpdateOperations.Add)
{
this.ValidateAuthorization("Products", PrivilegeConstants.SqlCreatePrivilege);
}
else if (operations == UpdateOperations.Delete)
{
this.ValidateAuthorization("Products", PrivilegeConstants.SqlDeletePrivilege);
var entry = default(ObjectStateEntry);
if (this.CurrentDataSource.ObjectStateManager.TryGetObjectStateEntry(product, out entry))
{
// Only a discontinued Product can be deleted.
if (!(bool)entry.OriginalValues["Discontinued"])
{
throw new DataServiceException(400, "Bad Request", "Products that are not discontinued cannot be deleted.", "en-US", null);
}
}
else
{
throw new DataServiceException(404, "Not Found", "The requested product could not be found in the data source.", "en-US", null);
}
}
}
private static string BuildMessage(string entitySetName, string privilege)
{
var message = string.Empty;
switch (privilege)
{
case PrivilegeConstants.SqlCreatePrivilege:
message = string.Format(CultureInfo.InvariantCulture, "You are not authorized to create new rows in the {0} entity set.", entitySetName);
break;
case PrivilegeConstants.SqlReadPrivilege:
message = string.Format(CultureInfo.InvariantCulture, "You are not authorized to query the {0} entity set.", entitySetName);
break;
case PrivilegeConstants.SqlUpdatePrivilege:
message = string.Format(CultureInfo.InvariantCulture, "You are not authorized to update rows in the {0} entity set.", entitySetName);
break;
case PrivilegeConstants.SqlDeletePrivilege:
message = string.Format(CultureInfo.InvariantCulture, "You are not authorized to delete rows in the {0} entity set.", entitySetName);
break;
default:
message = string.Format(CultureInfo.InvariantCulture, "You are not authorized to access the {0} entity set.", entitySetName);
break;
}
return message;
}
private void ValidateAuthorization(string entitySetName, string privilege)
{
if (!this.userPrivilegesRepository.HasUserPrivilege(this.UserId, privilege))
{
// The user does not have Read permission.
throw new DataServiceException(401, "Unauthorized", BuildMessage(entitySetName, privilege), "en-US", null);
}
}
}
}
on the client, the Product model class:
[EntitySetAttribute("Products")]
[DataServiceKeyAttribute("ProductID")]
public class Product : INotifyPropertyChanged
{
private int id;
private string productName;
private int? supplierID;
private int? categoryID;
private string quantityPerUnit;
private decimal? unitPrice;
private short? unitsInStock;
private short? unitsOnOrder;
private short? reorderLevel;
private bool discontinued;
public event PropertyChangedEventHandler PropertyChanged;
public int ProductID
{
get
{
return this.id;
}
set
{
this.id = value;
this.OnPropertyChanged("ProductID");
}
}
public string ProductName
{
get
{
return this.productName;
}
set
{
this.productName = value;
this.OnPropertyChanged("ProductName");
}
}
public int? SupplierID
{
get
{
return this.supplierID;
}
set
{
this.supplierID = value;
this.OnPropertyChanged("SupplierID");
}
}
public int? CategoryID
{
get
{
return this.categoryID;
}
set
{
this.categoryID = value;
this.OnPropertyChanged("CategoryID");
}
}
public string QuantityPerUnit
{
get
{
return this.quantityPerUnit;
}
set
{
this.quantityPerUnit = value;
this.OnPropertyChanged("QuantityPerUnit");
}
}
public decimal? UnitPrice
{
get
{
return this.unitPrice;
}
set
{
this.unitPrice = value;
this.OnPropertyChanged("UnitPrice");
}
}
public short? UnitsInStock
{
get
{
return this.unitsInStock;
}
set
{
this.unitsInStock = value;
this.OnPropertyChanged("UnitsInStock");
}
}
public short? UnitsOnOrder
{
get
{
return this.unitsOnOrder;
}
set
{
this.unitsOnOrder = value;
this.OnPropertyChanged("UnitsOnOrder");
}
}
public short? ReorderLevel
{
get
{
return this.reorderLevel;
}
set
{
this.reorderLevel = value;
this.OnPropertyChanged("ReorderLevel");
}
}
public bool Discontinued
{
get
{
return this.discontinued;
}
set
{
this.discontinued = value;
this.OnPropertyChanged("Discontinued");
}
}
public static Product CreateProduct(int productID, string productName, bool discontinued)
{
return new Product
{
ProductID = productID,
ProductName = productName,
Discontinued = discontinued,
};
}
protected virtual void OnPropertyChanged(string changedProperty)
{
var propertyChanged = this.PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(changedProperty));
}
}
}
}
And the NorthwindContext class:
public class NorthwindContext : DataServiceContext
{
public NorthwindContext(Uri serviceRoot)
: base(serviceRoot)
{
this.MergeOption = MergeOption.OverwriteChanges;
this.SaveChangesDefaultOptions = SaveChangesOptions.ContinueOnError;
}
public void AddToCategories(Category category)
{
this.AddObject("Categories", category);
}
public void AddToProducts(Product product)
{
this.AddObject("Products", product);
}
public void AddToSuppliers(Supplier supplier)
{
this.AddObject("Suppliers", supplier);
}
public void AttachToCategories(Category category)
{
this.AttachTo("Categories", category);
}
public void AttachToProducts(Product product)
{
this.AttachTo("Products", product);
}
public void AttachToSuppliers(Supplier supplier)
{
this.AttachTo("Suppliers", supplier);
}
}
}
and here is the ProductsPageViewModel class :
public class ProductsPageViewModel : ListViewModel<Product>
{
public ProductsPageViewModel()
: this(Deployment.Current.Dispatcher, App.CloudClientFactory.ResolveNorthwindContext())
{
}
public ProductsPageViewModel(Dispatcher dispatcher, NorthwindContext northwindContext)
: base(dispatcher, northwindContext)
{
}
protected override string EntitySetName
{
get
{
return "Products";
}
}
}
}
When you are working with EF, it doesn't suppose any direct queries to the database. Spent some time reading what is Domain Driven Design. There is described strategy Persistent Ignorance, which means, that when you are designing your system you should not consider data storage at all. Work only with the model. Data Mapper pattern describes the place where all the things related with the database should be done. Here is good article, which I think can help you.
Another advice, do not forget that MVC supports restful style of Web Development. Leveraging these capabilities should be helpful in your design.
paramosh,
So are you able to explain it to a newbie or not? I just went to that website, and read through that page, but it wasn't really much help for trying to lean the EF network (it's mainly reinforcing how I did things prior to EF).

Auto-mock container: Rhino Mocks and NInject

Does anyone have an implementation lying around of an auto-mock container using Rhino Mocks and NInject?
OK I built one myself using the Moq integration as a starting point. It is very simple. You need these 3 classes:
public class AutoMockingKernel : StandardKernel
{
private readonly IMockProvider _mockProvider;
public void Reset()
{
Components.Get<ICache>().Clear();
}
protected override bool HandleMissingBinding(Type service)
{
var isSelfBindable = TypeIsSelfBindable(service);
var binding = new Binding(service)
{
ProviderCallback = isSelfBindable
? StandardProvider.GetCreationCallback(service)
: _mockProvider.GetCreationCallback(),
IsImplicit = true
};
if (!isSelfBindable)
binding.ScopeCallback = ctx => null;
AddBinding(binding);
return true;
}
public AutoMockingKernel(IMockProvider mockProvider, INinjectSettings settings, params INinjectModule[] modules)
: base(settings, modules)
{
_mockProvider = mockProvider;
}
public AutoMockingKernel(IMockProvider mockProvider, params INinjectModule[] modules)
: base(modules)
{
_mockProvider = mockProvider;
}
}
internal class RhinoMockProvider : IProvider
{
public Type Type { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="RhinoMockProvider"/> class.
/// </summary>
public RhinoMockProvider(Type type)
{
Type = type;
}
public object Create(IContext context)
{
return MockRepository.GenerateMock(Type, Type.EmptyTypes);
}
}
public class RhinoAutoMockProvider : IMockProvider
{
public Func<IContext, IProvider> GetCreationCallback()
{
return ctx => new RhinoMockProvider(ctx.Request.Service);
}
}
You can then create an auto-mocking kernel in your unit test like this:
[Test]
public void Test()
{
var kernel = new AutoMockingKernel(new RhinoAutoMockProvider());
... etc
}
There is a RhinoMocks integration extension available.