At my current project(blazor server side) I want to start using the session storage for user data like roles and names.
I've tried Blazored.SessionStorage and AspNetCore.Components.Server.ProtectedBrowserStorage.
The problem I'm facing is, that I just can't get the value(it's always null) and I don't know why.
Code I'm using:
public void GetUserInfo()
{
var x = sessionStorage.GetAsync<string>("Name");
var y = sessionStorage.GetAsync<string>("Email");
string Name = x.ToString();
string Email = y.ToString();
}
And
[Inject] public ProtectedSessionStorage sessionStorage { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
string Name = Helper.Name;
string Email = Helper.Email;
await sessionStorage.SetAsync("Name", Name);
await sessionStorage.SetAsync("Email", Email);
var x = sessionStorage.GetAsync<string>("Name");
var y = sessionStorage.GetAsync<string>("Email");
Name = x.Result.Value;
Email = y.Result.Value;
}
Thanks to everyone in advance and have a great day! :)
DO NOT USE THIS SOLUTION AS IS. WHEN I GET THE TIME I WILL UPDATE IT TO A WORKING SOLUTION
I suggest adding this as an injected object using Dependency Injection.
Create a class to hold this information and add is as a Scoped service.
Class:
public class UserInfo : IUserInfo //Create an interface
{
public static Name { get; set; }
public static Email { get; set; }
}
Injection (Program.cs on .NET 6):
public static async Task Main(string[] args)
{
//For WSAM
var builder = WebAssemblyHostBuilder.CreateDefault(args);
//For Server
var builder = WebApplication.CreateBuilder(args);
...
builder.Services.AddScoped<IUserInfo, UserInfo>(); //Scoped Service injection
}
Add data to injected service:
[Inject]
public IUserInfo UserInfo { get; set; }
protected override void OnInitialized() //Use whatever Life Cycle methods works for your implementation
{
UserInfo.Name = Helper.Name;
UserInfo.Email = Helper.Email;
}
Usage example:
#inject IUserInfo UserInfo
#page "/"
<div>#UserInfo.Name</div>
<div>#UserInfo.Email</div>
Related
I used following only controller in my project out of entire following project.
https://github.com/graphql-dotnet/examples/blob/master/src/AspNetWebApi/Example/Controllers/GraphQLController.cs
Here Controller file is as below.
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using GraphQL.Http;
using GraphQL.Instrumentation;
using GraphQL.Types;
using GraphQL.Validation.Complexity;
namespace GraphQL.GraphiQL.Controllers
{
public class GraphQLController : ApiController
{
private readonly ISchema _schema;
private readonly IDocumentExecuter _executer;
private readonly IDocumentWriter _writer;
private readonly IDictionary<string, string> _namedQueries;
public GraphQLController(
IDocumentExecuter executer,
IDocumentWriter writer,
ISchema schema)
{
_executer = executer;
_writer = writer;
_schema = schema;
_namedQueries = new Dictionary<string, string>
{
["a-query"] = #"query foo { hero { name } }"
};
}
// This will display an example error
[HttpGet]
public Task<HttpResponseMessage> GetAsync(HttpRequestMessage request)
{
return PostAsync(request, new GraphQLQuery { Query = "query foo { hero }", Variables = null });
}
[HttpPost]
public async Task<HttpResponseMessage> PostAsync(HttpRequestMessage request, GraphQLQuery query)
{
var inputs = query.Variables.ToInputs();
var queryToExecute = query.Query;
if (!string.IsNullOrWhiteSpace(query.NamedQuery))
{
queryToExecute = _namedQueries[query.NamedQuery];
}
var result = await _executer.ExecuteAsync(_ =>
{
_.Schema = _schema;
_.Query = queryToExecute;
_.OperationName = query.OperationName;
_.Inputs = inputs;
_.ComplexityConfiguration = new ComplexityConfiguration { MaxDepth = 15 };
_.FieldMiddleware.Use<InstrumentFieldsMiddleware>();
}).ConfigureAwait(false);
var httpResult = result.Errors?.Count > 0
? HttpStatusCode.BadRequest
: HttpStatusCode.OK;
var json = _writer.Write(result);
var response = request.CreateResponse(httpResult);
response.Content = new StringContent(json, Encoding.UTF8, "application/json");
return response;
}
}
public class GraphQLQuery
{
public string OperationName { get; set; }
public string NamedQuery { get; set; }
public string Query { get; set; }
public Newtonsoft.Json.Linq.JObject Variables { get; set; }
}
}
When I try to call this controller, it gives me following error.
InvalidOperationException: Unable to resolve service for type 'GraphQL.Http.IDocumentWriter' while attempting to activate 'MyWebAppNamespace.Controllers.GraphQLController'.
Do I need any startup configuration or I can use this standalone controller? What am I missing?
Do I need any startup configuration or I can use this standalone controller? What am I missing?
As the error describes, it happens because the DI container cannot resolve service for IDocumentWriter.
It seems that you're missing some service registration. Did you forget to add the IDocumentWrite service ?
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDependencyResolver>(s => new FuncDependencyResolver(s.GetRequiredService));
services.AddSingleton<IDocumentExecuter, DocumentExecuter>();
services.AddSingleton<IDocumentWriter, DocumentWriter>();
// ...
services.AddSingleton<ISchema, StarWarsSchema>();
// ...
}
For more details, see startup here
or I can use this standalone controller?
No. You're not supposed to do that. That's because your controller depends on the IDocumentExecuter, IDocumentWriter, and ISchema service. They're all resolved by Dependency Injection. You have to register all the services before resolve the controller.
I am creating a web api project and want to add validation to my model, so I added a DataAnnotation attribute.
I then tested the project by trying to pass my object from a separate mvc project. I recieved a 500 server error.
Removing the DataAnnotation allows me to pass the object successfully. Why?
I have looked at a couple of tutorials such as this and this, they show how to handle validation errors, but this has not helped.
UPDATE
Removing the data annotation from MyProperty in Class1, solution B (but leaving it on the class in solution A) means values can be passed successfully! Is this a problem with deserilazing the object? If so how do I solve it?
B = My web service reciving the object
A = My mvc project sending the object
my code to send the resquest
public class Class1
{
[Required(ErrorMessage = "MyProperty value is required")]//remove this line to make it work
public int MyProperty { get; set; }
public Class2 MyOtherProperty { get; set; }
}
public class Class2
{
public string SomeProperty { get; set; }
}
async Task<string> Test2()
{
var form = new Class1();
form.MyProperty = 123;
form.Class2 = new Class2();
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:58814/api/");
var post = await client.PostAsJsonAsync<Class1>("Values", form);
var putt = await client.PutAsJsonAsync<Class1>("Values", form);
}
return "";
}
my code to recieve the request (the breakpoint applied is not being hit)
// POST api/values
public void Post([FromBody]Class1 value)
{
}
// PUT api/values/5
public void Put([FromBody]Class1 value)
{
}
I have resolve the issue thanks to the advice from this link - Scott Hanselman's blog
My sending project and receiving project had identical classes (including data annotations). Removing the annotations from the class in the receiving project resolved the binding issue but I still needed validation on the properties. Also changing the annotation from required to Range also resolved the binding issue (I only mention these as they were some steps I took to try and debug).
The final solution for me was to change this
public class Network
{
[Required(ErrorMessage = "NetworkID is required")]
public int NetworkID { get; set; }
}
to this
[DataContract]
public class Network
{
[DataMember(IsRequired = true)]
public int NetworkID { get; set; }
}
I am trying to figure out how to create a second DB context in EF7 RC1. In the past I could use a constructor with :base("connectionName") but that no longer seems an option since it says cannot convert string to System.IServiceProvider.
My second context code is as follows:
public class DecAppContext : DbContext
{
public DecAppContext()
// :base("DefaultConnection")
{
}
public DbSet<VignetteModels> VignetteModels { get; set; }
public DbSet<VignetteResult> Result { get; set; }
}
}
In my config.json I have the connection specified:
"Data": {
"DefaultConnection": {
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-xxxxx...;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
In my configure services section of my startup I have both contexts added:
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]))
.AddDbContext<DecAppContext>(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
The applicationDB context works fine since I can create a user and login without issue
However when I try to access the other context as in my controller via:
private DecAppContext db = new DecAppContext();
var vignette = db.VignetteModels.SingleOrDefault(v => v.CaseId == vid);
I get the error:
No database providers are configured. Configure a database provider by
overriding OnConfiguring in your DbContext class or in the
AddDbContext method when setting up services.
Any working examples in EF7 RC1 with multiple db contexts and accessing them would be much appreciated.
First of all I would recommend you the article from the wiki of EntityFramework on GitHub. The article describes many ways to define DbContext, which references to a section of appsettings.json. I personally prefer the way with the usage of [FromServices] attribute.
The code could be about the following:
First of all you defined appsettings.json with the following content
{
"Data": {
"ApplicationDbConnectionString": "Server=(localdb)\\mssqllocaldb;Database=ApplicationDb;Trusted_Connection=True;MultipleActiveResultSets=true",
"DecAppDbConnectionString": "Server=Server=(localdb)\\mssqllocaldb;Database=DecAppDb;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
where you define two connection strings.
Seconds you declare the classes DecAppContext and ApplicationDbContext which have DbContext as the base class. The simplest form will be just
public class ApplicationDbContext : DbContext
{
}
public class DecAppContext : DbContext
{
}
without any DbSet properties.
Third Step. You use Microsoft.Extensions.DependencyInjection to inject the database contexts. To do this you need just include in Startup.cs something like
public class Startup
{
// property for holding configuration
public IConfigurationRoot Configuration { get; set; }
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
// save the configuration in Configuration property
Configuration = builder.Build();
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc()
.AddJsonOptions(options => {
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<ApplicationDbContext>(options => {
options.UseSqlServer(Configuration["Data:ApplicationDbConnectionString"]);
})
.AddDbContext<DecAppContext>(options => {
options.UseSqlServer(Configuration["Data:DecAppDbConnectionString"]);
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
}
}
Se create two DbContext (DecAppContext and ApplicationDbContext) using the configuration "Data:DecAppDbConnectionString" and "Data:ApplicationDbConnectionString".
Now we can just use the context in the controller. For example
[Route("api/[controller]")]
public class UsersController : Controller
{
[FromServices]
public ApplicationDbContext ApplicationDbContext { get; set; }
[FromServices]
public DecAppContext DecAppContext { get; set; }
[HttpGet]
public IEnumerable<object> Get() {
var returnObject = new List<dynamic>();
using (var cmd = ApplicationDbContext.Database.GetDbConnection().CreateCommand()) {
cmd.CommandText = "SELECT Id, FirstName FROM dbo.Users";
if (cmd.Connection.State != ConnectionState.Open)
cmd.Connection.Open();
var retObject = new List<dynamic>();
using (var dataReader = cmd.ExecuteReader())
{
while (dataReader.Read())
{
var dataRow = new ExpandoObject() as IDictionary<string, object>;
for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++)
dataRow.Add(
dataReader.GetName(iFiled),
dataReader.IsDBNull(iFiled) ? null : dataReader[iFiled] // use null instead of {}
);
retObject.Add((ExpandoObject)dataRow);
}
}
return retObject;
}
}
}
or the same using async/await:
[Route("api/[controller]")]
public class UsersController : Controller
{
[FromServices]
public ApplicationDbContext ApplicationDbContext { get; set; }
[FromServices]
public DecAppContext DecAppContext { get; set; }
[HttpGet]
public async IEnumerable<object> Get() {
var returnObject = new List<dynamic>();
using (var cmd = ApplicationDbContext.Database.GetDbConnection().CreateCommand()) {
cmd.CommandText = "SELECT Id, FirstName FROM dbo.Users";
if (cmd.Connection.State != ConnectionState.Open)
cmd.Connection.Open();
var retObject = new List<dynamic>();
using (var dataReader = await cmd.ExecuteReaderAsync())
{
while (await dataReader.ReadAsync())
{
var dataRow = new ExpandoObject() as IDictionary<string, object>;
for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++)
dataRow.Add(dataReader.GetName(iFiled), dataReader[iFiled]);
retObject.Add((ExpandoObject)dataRow);
}
}
return retObject;
}
}
}
One can just declare the property public ApplicationDbContext ApplicationDbContext { get; set; } with the attribute [FromServices] and ASP.NET initialize it from the context injected in ConfigureServices. In the same way one can use the second context DecAppContext whenever you need it.
The above code example will execute SELECT Id, FirstName From dbo.Users in the database context and return JSON data in the form [{"id":123, "firstName":"Oleg"},{"id":456, "firstName":"Xaxum"}]. The conversion of property names from Id and FirstName to id and firstName will be done automatically during serialization because of usage AddJsonOptions in ConfigureServices.
UPDATE: I have to reference the announcement. The next version of MVC (RC2) will require to change the above code to use [FromServices] as additional parameter (of method Get() for example) instead of usage public property [FromServices] public ApplicationDbContext ApplicationDbContext { get; set; }. One will need to remove the property ApplicationDbContext and to add additional parameter to Get() method: public async IEnumerable<object> Get([FromServices] ApplicationDbContext applicationDbContext) {...}. Such changes can be easy done. See here and example of the changes in the demo example of MVC:
[Route("api/[controller]")]
public class UsersController : Controller
{
[HttpGet]
public async IEnumerable<object> Get(
[FromServices] ApplicationDbContext applicationDbContext,
[FromServices] DecAppContext decAppContext)
{
var returnObject = new List<dynamic>();
// ... the same code as before, but using applicationDbContext
// and decAppContext parameters instead of ApplicationDbContext
// and DecAppContext properties
}
I am a newbie to with unity and unit of work pattern and I am trying to write a code, which connects to my webservice and does all the work.
Everything goes well until I use the Database but I get lost when I try to use the webservice.
I have wasted my 2 precious days, searching every single possible article related to it and applying it to my code, but no luck till date.
I know, by writing connection string to web.config and calling it in dbcontext class controller will connect to the required database, but I am not connecting to any database, so what changes I need to do in web/app.config. Also, even if I write my connection logic in dbcontext constructor, it still searches and fills the dbcontext with sql server details. I presume thats happening because I am using DBSet.
Guys, you are requested to have a look at my code, I have done and show me some hope that I can do it. Let me know, if you want any other info related to the code that you want to see.
thanks
DBCONTEXT
public class CVSContext : DbContext
{
public DbSet<CVSViewModel> CVS { get; set; }
public DbSet<Contact> Contacts { get; set; }
public DbSet<Account> Accounts { get; set; }
public CVSContext()
{
//CRM Start
var clientCredentials = new System.ServiceModel.Description.ClientCredentials();
clientCredentials.UserName.UserName = "";
clientCredentials.UserName.Password = "";
var serviceProxy = new Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy(new Uri("http://Organization.svc"), null, clientCredentials, null);
serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());
HttpContext.Current.Session.Add("ServiceProxy", serviceProxy);
//CRM End
}
}
GENERIC REPOSITORY
public class GenericRepository<TEntity> where TEntity : class
{
internal CVSContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(CVSContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
}
UNIT OF WORK
public interface IUnitOfWork : IDisposable
{
int SaveChanges();
}
public interface IDALContext : IUnitOfWork
{
ICVSRepository CVS { get; set; }
IContactRepository Contacts { get; set; }
//IAccountRepository Accounts { get; set; }
}
public class DALContext : IDALContext
{
private CVSContext dbContext;
private ICVSRepository cvs;
private IContactRepository contacts;
// private IAccountRepository accounts;
public DALContext()
{
dbContext = new CVSContext();
}
public ICVSRepository CVS
{
get
{
if (cvs == null)
cvs = new CVSRepository(dbContext);
return cvs;
}
set
{
if (cvs == value)
cvs = value;
}
}
public IContactRepository Contacts
{
get
{
if (contacts == null)
contacts = new ContactRepository(dbContext);
return contacts;
}
set
{
if (contacts == value)
contacts = value;
}
}
public int SaveChanges()
{
return this.SaveChanges();
}
public void Dispose()
{
if(contacts != null)
contacts.Dispose();
//if(accounts != null)
// accounts.Dispose();
if(dbContext != null)
dbContext.Dispose();
GC.SuppressFinalize(this);
}
}
SERVICE
public interface ICVSService
{
Contact CreateContact(Guid contactName, string productName, int price);
List<CVSViewModel> GetCVS();
List<Contact> GetContacts();
List<Account> GetAccounts();
}
public class CVSService : ICVSService, IDisposable
{
private IDALContext context;
public CVSService(IDALContext dal)
{
context = dal;
}
public List<CVSViewModel> GetCVS()
{
return context.CVS.All().ToList();
}
public List<Contact> GetContacts()
{
return context.Contacts.All().ToList();
}
public List<Account> GetAccounts()
{
return context.Accounts.All().ToList();
}
public Contact CreateContact(Guid contactName, string accountName, int price)
{
var contact = new Contact() { ContactId = contactName };
var account = new Account() { ContactName = accountName, Rent = price, Contact = contact };
//context.Contacts.Create(contact);
context.SaveChanges();
return contact;
}
public void Dispose()
{
if (context != null)
context.Dispose();
}
}
CONTROLLER
public ActionResult Index()
{
ViewData.Model = service.GetContacts();
return View();
}
It's all about proper abstractions. The common abstraction that is used between some data source (could be a db or ws) is the Repository pattern, or at a higher level the Unit of Work pattern. In fact Entity Framework DbContext is an implementation of the Unit of Work pattern, but it is tailored for databases. You can't use to communicate with a web service.
In that case you will have to write your own IRepository<T> abstraction and have a database specific implementation that uses a DbContext under the covers and a web service specific implementation that wraps a web service client proxy under the covers.
However, when your application gets more complex, you often find yourself wanting to have some sort of transaction like behavior. This is what the Unit of Work pattern if for: it presents a business transaction. Using the unit of work pattern to wrap multiple WS calls however, will get painful very soon. It's a lot of work to get right and in that case you will be much better of using a message based architecture.
With a message based architecture you define a single atomic operation (a business transaction or use case) as a specific message, for instance:
public class MoveCustomerCommand
{
public int CustomerId { get; set; }
public Address NewAddress { get; set; }
}
This is just an object (DTO) with a set of properties, but without behavior. Nice about this is that you can pass these kinds of objects over the wire using WCF or any other technology or process them locally without the need for the consumer to know.
Take a look at this article that describes it in detail. This article builds on top of that model and describes how you can write highly maintainable WCF services using this model.
Please can someone help me because I am getting confused.
I have an Entity like this:
public class Code
{
public int ID { get; set; }
public int UserID { get; set; }
public string CodeText { get; set; }
}
and an Interface like this:
public interface ICodeRepository
{
IQueryable<Code> Codes { get; }
void AddCode(Code code);
void RemoveCode(Code code);
Code GetCodeById(int id);
}
and a Repository like this:
public class SQLCodeRepository : ICodeRepository
{
private EFSQLContext context;
public SQLCodeRepository()
{
context = new EFSQLContext();
}
public IQueryable<Code> Codes
{
get { return context.Codes; }
}
public void AddCode(Code code)
{
context.Codes.Add(code);
context.SaveChanges();
}
public void RemoveCode(Code code)
{
context.Codes.Remove(code);
context.SaveChanges();
}
public Code GetCodeById(int id)
{
return context.Codes.Where(x => x.ID == id).FirstOrDefault();
}
}
and a Context like this:
public class EFSQLContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Code> Codes { get; set; }
public DbSet<PortfolioUser> PortfolioUsers { get; set; }
}
If I declare my controller like this:
public class SearchController : Controller
{
private ICodeRepository cRepo;
public SearchController(ICodeRepository codeRepository)
{
cRepo = codeRepository;
}
}
and then try to do cRepo.GetCodeById(1) nothing happens. But if I declare private ICodeRepository rep = new SQLCodeRepository and then call rep.GetCodeById(1) I can see the method in the Repository being called.
What am I doing wrong?
It looks like from the constructor signature, you are going to be doing some dependency injection. The step you are missing is to set up a DI container using a tool like Castle Windsor. You then configure the MVC resolver to use the DI container to give you the correct implementation of ICodeRepository.
See this
You'll need to create a resolver that implements IDependencyResolver and IDependencyScope and a controller factory that inheritsDefaultControllerFactory
Once you have those you can do something like the following:
MyContainer container; // this needs to be a class level member of the asax
var configuration = GlobalConfiguration.Configuration;
container = new MyContainer() // may need additional stuff here depending on DI tool used
configuration.DependencyResolver = new MyDependancyResolver(container);
var mvcControllerFactory = new MyFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(mvcControllerFactory);
You would call the above code from the asax Application_Start()
See this answer for more specifics on using Ninject and MVC3