OperationBehaviorAttribute inheritance - wcf

I have base class for my services. Attribute OperationBehavior doesn't apply if it defined in base class and I override method in derived class. Of cause, I can duplicate code, but maybe there is other way...
[ServiceContract]
public interface IMyService
{
[OperationContract]
void DoWork();
}
public class MyServiceBase
{
[OperationBehavior(TransactionScopeRequired = true)]
public virtual void DoWork()
{
}
}
public class MyService : MyServiceBase, IMyService
{
public override void DoWork()
{
//No Transaction, because attribute OperationBehavior doesn't apply.
}
}

You will need to do something like the following:
public class MyServiceBase
{
[OperationBehavior(TransactionScopeRequired = true)]
public void DoWork()
{
DoWorkImpl();
}
protected virtual DoWorkImpl()
{
}
}
public class MyService : MyServiceBase, IMyService
{
protected override void DoWorkImpl()
{
//Should have a Tx here now
}
}

Related

How to implement Service inherit from generic repository?

I work on asp.net core mvc blazor application , I have issue I can't implement service inherit from generic repository .
meaning how to inherit from IRepository to get functions below on class server names service :
Insert
Update
GetById
GetList
GetListAsync
Interface generic repository
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
public interface IRepository<TEntity> where TEntity : class
{
Task<int> Count(Expression<Func<TEntity, bool>> where);
TEntity GetByID(object id);
TEntity Insert(TEntity entity);
void Update(TEntity entityToUpdate);
Task<ICollection<TType>> Get<TType>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TType>> select) where TType : class;
Task<bool> Any(Expression<Func<TEntity, bool>> where);
TEntity GetFirst(Expression<Func<TEntity, bool>> where);
TEntity Single(Expression<Func<TEntity, bool>> where);
Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> where);
List<TEntity> GetList(Expression<Func<TEntity, bool>> where);
Task<bool> UpdateBasedOnCondition(Expression<Func<TEntity, bool>> where, Action<TEntity> select);
void Save();
}
class that implement interface as below :
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using UC.AppRepository.Core;
public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
internal AppsRepositoryDBContext _context;
internal DbSet<TEntity> dbSet;
public BaseRepository(AppsRepositoryDBContext context)
{
_context = context;
this.dbSet = _context.Set<TEntity>();
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual TEntity Insert(TEntity entity)
{
var result = dbSet.AddAsync(entity).Result.Entity;
Save();
return result;
}
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
_context.Entry(entityToUpdate).State = EntityState.Modified;
}
public virtual async Task<bool> UpdateBasedOnCondition(Expression<Func<TEntity, bool>> where, Action<TEntity> select)
{
try
{
var ListOfRecord = await dbSet.Where(where).ToListAsync();
if (null != ListOfRecord && ListOfRecord.Count > 0)
{
ListOfRecord.ForEach(select);
// Save();
await _context.SaveChangesAsync();
return true;
}
return false;
}
catch (Exception ex)
{
return false;
throw;
}
}
public async Task<ICollection<TType>> Get<TType>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TType>> select) where TType : class
{
if(where == null)
{
return await dbSet.Select(select).ToListAsync();
}
return await dbSet.Where(where).Select(select).ToListAsync();
}
public async Task<int> Count(Expression<Func<TEntity, bool>> where)
{
return await dbSet.Where(where).CountAsync();
}
public async virtual Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> where)
{
// var test = dbSet.Where(where).ToList();
return await dbSet.Where(where).ToListAsync();
}
public virtual List<TEntity> GetList(Expression<Func<TEntity, bool>> where)
{
return dbSet.Where(where).ToList();
}
public async Task<bool> Any(Expression<Func<TEntity, bool>> where)
{
return await dbSet.AnyAsync(where);
}
public TEntity GetFirst(Expression<Func<TEntity, bool>> where)
{
return dbSet.FirstOrDefault(where);
}
public TEntity Single(Expression<Func<TEntity, bool>> where)
{
return dbSet.Single(where);
}
public void Save()
{
try
{
_context.SaveChanges();
}
catch (Exception ex)
{
throw;
}
}
}
so I have class ServerNameService and class interface IserverNamesService
I need to implement insert,update,selectById,selectall functions for server name models
from base repository
public class ServerNameService:IRepository
{
// what i write here
}
public interface IserverNamesService:IRepository
{
// what i write here
}
public class ServerNames
{
[Key]
public int ServerID { get; set; }
public string Server_Name{ get; set; }
public string Server_Type { get; set; }
public string Operating_System { get; set; }
public string Version { get; set; }
public bool IsActive { get; set; }
}
I have issue I can't implement service inherit from generic repository.I have class ServerNameService and class interface IserverNamesService I need to implement insert,update,selectById,selectall functions for server name models from base repository
Well, to directly answer your question, to implement your ServerNameService which derived from IRepository that would would be as following:
IserverNamesService:
public interface IserverNamesService : IRepository<ServerNames>
{
}
Note: Keep it empty because we will use of IRepository and BaseRepository in ServerNamesService class to implement its members.
ServerNamesService:
public class ServerNamesService : BaseRepository<ServerNames>, IserverNamesService
{
public ServerNamesService(ApplicationDbContext context) : base(context)
{
}
public override ServerNames GetByID(object id)
{
return _context.ServerNames.Where(sn => sn.ServerID == (int)id).FirstOrDefault();
}
}
Controller:
[Route("api/[controller]")]
[ApiController]
public class ServerNamesServiceController : ControllerBase
{
private readonly IserverNamesService _serverNamesService;
public ServerNamesServiceController(IserverNamesService namesService)
{
_serverNamesService = namesService;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetById(object id)
{
var item = _serverNamesService.GetByID(id);
if (item == null)
return NotFound();
return Ok(item);
}
}
Program.cs:
builder.Services.AddScoped<IserverNamesService, ServerNamesService>();
Note: Register your ServerNamesService class in your program.cs
UnitOfWork Pattern Implementation:
As long your application would continue evolving and there would be ton of service class, in that scenario, you have to introduce lot of service in your controller. But if you would like to handle those smoothly, you could use UnitOfWork pattern which would contain all of your service together.
Interface:
public interface IUnitOfWork
{
IserverNamesService ServerNamesService { get; }
Task CompleteAsync();
}
Implementation:
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly ApplicationDbContext _context;
public IserverNamesService ServerNamesService { get; private set; }
public UnitOfWork(ApplicationDbContext context)
{
_context = context;
ServerNamesService = new ServerNamesService(context);
}
public async Task CompleteAsync()
{
await _context.SaveChangesAsync();
}
public void Dispose()
{
_context.Dispose();
}
}
Controller:
[Route("api/[controller]")]
[ApiController]
public class ServerNamesServiceController : ControllerBase
{
private readonly IUnitOfWork _unitOfWork;
public ServerNamesServiceController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetById(object id)
{
var item = _unitOfWork.ServerNamesService.GetByID(id);
if (item == null)
return NotFound();
return Ok(item);
}
}
Output:
Note: If you would like to know more details on repository pattern you could check our official document here and working sample here.
You should pass your Entity as generic type to IRepository in IServerNamesService, and then inheritance ServerNameService from IServerNamesService.
public interface IServerNamesService:IRepository<ServerNames>
{
// your methods interface
}
public class ServerNameService:IServerNamesService{
private readonly IRepository<ServerNames> _repository;
public class ServerNameService(IRepository<ServerNames> repository)
{
_repository = repository;
}
//body of your methods
}

Should service call another service or repository directly?

I am creating the WebApplication, with many layers (for now important are Model, Repository, BusinessLayer)
Having ClassService, ClassRepository and StudentService, StudentRepository, should ClassServiceMethod call methods from StudentService or StudentRepository?
Please provide as many arguments or additional links/blogs/informations as possible :)
Thanks in advance.
Here is my example code, some generics are added. The question is about GetClassAndBestStudent method:
Services - Business Layer
public class ClassService : BaseService<Class>, IClassService
{
IClassRepository classRepository; // Resolved by IoC, will be injected to BaseService
IStudentRepository studentRepository;
IStudentService studentService;
public virtual Class GetClassWithHighestNotes() { ... } // Do some stuff and call classRepository.GetClassWithHighestNotes()
public virtual Teacher GetTeachersByClass(int classId) { ... } // Do some stuff and call classRepository.GetTeachersByClass()
public virtual GetClassAndBestStudent(int classId)
{
// Question here: Which call is valid?
var best = studentRepository.GetStudentWithHighestNotes()
var best = studentService.GetStudentWithHighestNotes();
}
}
public class StudentService : BaseService<Student>, IStudentService
{
IStudentRepository studentRepository; // Resolved by IoC, will be injected to BaseService
public virtual IEnumerable<Student> GetStudentsByClass(int classId) { ... } // Do some stuff and call studentRepository.GetStudentsByClass()
public virtual Student GetStudentWithHighestNotes() { ... } // Do some stuff and call studentRepository.GetStudentWithHighestNotes()
}
// Abstract, generic CRUD service
public abstract class BaseService<T> : IBaseService<T> where T : MyBase
{
IRepository<T> repository;
public virtual IEnumerable<T> GetAll() { ... } // Do some stuff and call repository.GetAll()
public virtual T GetById(int id) { ... } // Do some stuff and call repository.GetById()
public virtual T Insert(T entity) { ... } // Do some stuff and call repository.Insert()
public virtual T Update(T entity) { ... } // Do some stuff and call repository.Update()
public virtual bool Delete(T entity) { ... } // Do some stuff and call repository.Delete()
public virtual bool Delete(int id) { ... } // Do some stuff and call repository.Delete()
}
Repositories - Data Layer
public class ClassRepository : BaseRepository<Class>, IClassRepository
{
public virtual Class GetClassWithHighestNotes() { ... }
public virtual Teacher GetTeachersByClass(int classId) { ... }
}
public class StudentRepository: BaseRepository<Student> IStudentRepository
{
public virtual IEnumerable<Student> GetStudentsByClass(int classId) { ... }
public virtual Student GetStudentWithHighestNotes() { ... }
}
// Abstract, generic CRUD repository
public abstract class BaseRepository<T> : IRepository<T> where T : MyBase
{
public virtual IEnumerable<T> GetAll() { ... }
public virtual T GetById(int id) { ... }
public virtual T Insert(T entity) { ... }
public virtual T Update(T entity) { ... }
public virtual bool Delete(T entity) { ... }
public virtual bool Delete(int id) { ... }
}
The best practice is calling StudentService from ClassServiceMethod. If the implementation in StudentRepository changes in the future, you can create another repository method like StudentRepositoryNew and utilize the same StudentService.

How to set the priority of the methods that are included in groups in testng.xml file?

I have a class which has 2 methods. Each method is having a group associated.
Now I want to set my testng.xml file in such a way that when testcase TC1 executes, Method1() and then Method2() will be called and when testcase TC2 will be executed, Method2() and then Method1() will be executed.
Is there any way by which I can do that?
You can move your test case methods to a helper class and then simply create a test class for each test case, define your methods with their test priorities and/or dependencies, and call your shared test method code. e.g.:
public class TestCaseMethods {
public static void method1() { /*...*/ }
public static void method2() { /*...*/ }
}
public class TC1 {
#Test
public void method1() {
TestCaseMethods.method1();
}
#Test(dependsOnMethods = {"method1"})
public void method2() {
TestCaseMethods.method2();
}
}
public class TC2 {
#Test(dependsOnMethods = {"method2"})
public void method1() {
TestCaseMethods.method1();
}
#Test
public void method2() {
TestCaseMethods.method2();
}
}
You can also use inheritance if you prefer:
public class AbstractTC {
public void method1() { /*...*/ }
public void method2() { /*...*/ }
}
public class TC1 extends AbstractTC {
#Override
#Test
public void method1() {
super.method1();
}
#Override
#Test(dependsOnMethods = {"method1"})
public void method2() {
super.method2();
}
}
public class TC2 extends AbstractTC {
#Test(dependsOnMethods = {"method2"})
public void method1() {
super.method1();
}
#Test
public void method2() {
super.method2();
}
}

WCF Interface as parameter

I am using interface as input parameter in OperationContract. But when i generate proxy class at client side. I am not able to access the members of interface or class implemeting the ITransaction interface. I am only geeting is object
Service Interface
[ServiceContract]
public interface IServiceInterface
{
[OperationContract]
string SyncDatabase(ITransaction TransactionObject);
}
Service class
class SyncService:IServiceInterface
{
public string SyncDatabase(ITransaction TransactionObject)
{
return "Hello There!!";
}
}
Interface
public interface ITransaction
{
ExpenseData ExpData { get; set; }
void Add(ITransaction transactionObject);
}
Data Contract
[DataContract]
public class Transaction:ITransaction
{
[DataMember]
public ExpenseData ExpData
{
get;
set;
}
public void Add(ITransaction transactionObject)
{
}
}
In above case should i also copy the iTransaction class and interface on client
You actually need to make your ServiceContract aware of the implementation of the interface you pass as a parameter, so WCF will include it in the WSDL.
This should work:
[ServiceContract]
[ServiceKnownType(typeof(Transaction))]
public interface IServiceInterface
{
[OperationContract]
string SyncDatabase(ITransaction TransactionObject);
}
Use [KnownType(typeof(testClass))].
Refer these links:
msdn.microsoft.com/en-us/library/ms730167.aspx
www.codeproject.com/Tips/108807/Implementing-KnownType-Attribute
Try making your interface the [DataContract] and use the [KnownType] attribute to tell WCF what the known implementations of that interface are.
[DataContract]
[KnownType(typeof(Transaction))]
public interface ITransaction
{
[DataMember]
ExpenseData ExpData { get; set; }
void Add(ITransaction transactionObject);
}

VS-generated clients of my service throw Deserialization exceptions

Our WCF service has just one method:
[ServiceContract(Name = "Service", Namespace = "http://myservice/")]
[ServiceKnownType("GetServiceKnownTypes", typeof(Service))]
public interface IService {
Response Execute(Request request);
}
public class Service : IService {
public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider provider) {
return KnownTypesResolver.GetKnownTypes();
}
public Response Execute(Request request) {
return new MyResponse { Result = MyEnumHere.FirstValue };
}
}
Both the Request and Response class includes a ParameterCollection member.
[Serializable]
[CollectionDataContract(Name = "ParameterCollection", Namespace = "http://myservice/")]
[KnownType("GetKnownTypes")]
public class ParameterCollection : Dictionary<string, object> {
private static IEnumerable<Type> GetKnownTypes()
{
return KnownTypesResolver.GetKnownTypes();
}
}
Subclasses of Request and Response store their values into the ParameterCollection value bag.
I am using the KnownTypesResolver class to provide type information across all Service objects.
public static class KnownTypesResolver {
public static IEnumerable<Type> GetKnownTypes()
{
var asm = typeof(IService).Assembly;
return asm
.GetAllDerivedTypesOf<Response>() // an extension method
.Concat(new Type[] {
typeof(MyEnumHere),
typeof(MyEnumHere?),
typeof(MyClassHere),
typeof(MyClassListHere),
});
}
}
If I'm not mistaken, everything should have proper type information for proxy class generation tools to produce well-defined classes client-side.
However, whenever one of the Response subclasses (i.e. MyResponse) contains an enum value such as MyEnumHere, WCF starts complaining that the deserializer has no knowledge of the MyEnumHere value. It should have. I provided a KnownTypeAttribute for this very reason.
The client-side proxy class does have a MyEnumHere enum in the Reference.cs file; the problem is that the ParameterCollection class has no KnownTypeAttributes generated for it.
I resorted to hand-editing and including the following lines in the generated Reference.cs file:
//>
[KnownTypeAttribute(typeof(MyEnumHere))]
[KnownTypeAttribute(typeof(MyEnumHere?))]
[KnownTypeAttribute(typeof(MyClassHere))]
[KnownTypeAttribute(typeof(MyClassListHere))]
//<
public class ParameterCollection : Dictionary<string, object> { /* ... */ }
Hand-editing generated files is horrible. But this makes the clients work. What am I doing wrong? How can I define my Service objects so that the VS-proxy classes that are generated are correct from the get-go?
Thanks for your time.
WCF does not work well with Dictionary because it is not interoperable. You may use Array, List or custom collection to make sure that your data is properly serialized.
Code below uses List<ParamCollectionElement> instead of Dictionary. I also removed some redundant attributes.
[DataContract]
public class Request
{
[DataMember]
public ParameterCollection ParameterCollection { get; set; }
}
[DataContract]
public class Response
{
[DataMember]
public ParameterCollection ParameterCollection { get; set; }
}
[DataContract]
public class MyResponse : Response
{
[DataMember]
public MyEnumHere Result { get; set; }
}
public class ParamCollectionElement
{
public string Key { get; set; }
public object Value { get; set; }
}
[CollectionDataContract(Name = "ParameterCollection")]
public class ParameterCollection : List<ParamCollectionElement>
{
}
public static class KnownTypesResolver
{
public static IEnumerable<Type> GetKnownTypes()
{
return
new Type[] {
typeof(MyEnumHere),
typeof(MyEnumHere?),
typeof(Request),
typeof(Response),
typeof(MyResponse)
};
}
}
[DataContract]
public enum MyEnumHere
{
[EnumMember]
FirstValue,
[EnumMember]
SecondValue
}
[ServiceKnownType("GetServiceKnownTypes", typeof(Service))]
[ServiceContract(Name = "Service")]
public interface IService
{
[OperationContract]
Response Execute(Request request);
}
public class Service : IService
{
public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider provider)
{
return KnownTypesResolver.GetKnownTypes();
}
public Response Execute(Request request)
{
var result = new MyResponse
{
Result = MyEnumHere.FirstValue,
ParameterCollection = new ParameterCollection()
};
result.ParameterCollection.Add(new ParamCollectionElement {Key = "one", Value = MyEnumHere.FirstValue});
result.ParameterCollection.Add(new ParamCollectionElement { Key = "two", Value = new Response() });
return result;
}
}
Make sure you have [DataContract] on your enum and [EnumMember] on each of the enum members:
[DataContract]
public enum MyEnumHere
{
[EnumMember]
SomeValue,
[EnumMember]
OtherValue,
[EnumMember]
OneMoreValue
}
That should cause the proxy-enum to be built out (with its member values) in your client without having to manually change the Reference.cs file.