I created a project to expose some actions of a MVC app to a Winforms app one of these actions must save a new visitor to the database, i have a MVC project that has a reference to a local service(using EF6) project that writes on the database thast OK!, but when i create the WCF project to use the service project and call the write method, this complete ok with no errors but doesn´t write the data.
Here is the code of my WCF
public async Task<bool> CreateAsync(VisitanteComposite item)
{
try
{
var myTask = Task.Factory.StartNew(() => _visitanteServicio.Create(Mapper.Map<Visitante>(item)));
await myTask;
return myTask.IsCompleted;
}
catch (Exception)
{
return false;
}
}
These is the generic create Method
public virtual void Create(T item)
{
try
{
Repositorio.Add(item);
UnitOfWork.SaveChanges();
}
catch (Exception ex)
{
//_logger.Debug(item.GetType() + " Error al crear: " + ex.Message);
throw new ServiceException("Ocurrio un error al crear el item", ex);
}
}
These is the repository method
public virtual void Add(T entity)
{
DbContext.Set<T>().Add(entity);
}
I rewrite the WCF to this and work
public async Task<bool> CreateAsync(VisitanteComposite item)
{
try
{
var myTask = Task.Factory.StartNew(() =>
{
using (var db = new ModelContainer())
{
var visitante = new Visitante
{
Apellido = item.Apellido,
Nombre = item.Nombre,
TipoDocumentoId = item.TipoDocumentoId,
NumeroDocumento = item.NumeroDocumento
};
AplicarFiltros(visitante);
db.Set<Visitante>().Add(visitante);
db.SaveChanges();
}
});
await myTask;
return myTask.IsCompleted;
}
catch (Exception)
{
return false;
}
}
but i want to reuse the previous methods
Related
I created a simple WPF client app in .net6.0 and incorporated WebView2 control.
I deployed/copied this app to a different machine and also installed .NET6.0 runtime there.
Upon running this app, I only see the main window and NO WebView2 initialized/created.
Note this the same implementation is working on my dev machine.
public MainWindow()
{
InitializeComponent();
InitializeWebView2();
}
private async Task InitializeWebView2()
{
//myPanel.Children.Add(webView2);
//await webView2.EnsureCoreWebView2Async();
((Action)(async () =>
{
try
{
CoreWebView2Environment env = await CoreWebView2Environment.CreateAsync(null, "another_dir");
WebView2 webview = new WebView2();
/*
webview.Source = new Uri("https://www.bing.com");
*/
var result = webview.EnsureCoreWebView2Async(env).GetAwaiter();
result.OnCompleted(() =>
{
try
{
result.GetResult();
}
catch (Exception e)
{
Console.WriteLine(e);
}
});
myPanel.Children.Add(webview);
webview.NavigateToString("https://google.com");
}
catch (Exception e)
{
Console.WriteLine(e);
}
})).Invoke();
}
EnsureCoreWebView2Async is supposed to be awaited before you set the Source:
private async Task InitializeWebView2()
{
var webview = new WebView2();
myPanel.Children.Add(webview);
var env = await CoreWebView2Environment.CreateAsync(null, "another_dir");
var result = await webview.EnsureCoreWebView2Async(env);
webview.Source = new Uri("https://www.bing.com");
}
I am trying to develop a data access service using Visual Studio 2019, .Net Core 3.0. I am using NancyFX to handle http requests. this is working just fine as a console application. When I build and run, then in browser go to HTTP://localhost/, it returns the proper data. I have a working Nancy module to handle requests. Here is original Main code:
static void Main(string[] args)
{
Logger.LogInfo("NancyDataService starting...");
var uri = new Uri(ConfigurationManager.AppSettings["uri"]);
var hostConfig = new HostConfiguration();
hostConfig.UrlReservations.CreateAutomatically = true;
hostConfig.RewriteLocalhost = false;
using (var nancyHost = new NancyHost(uri, new AppBootstrapper(), hostConfig))
{
try
{
nancyHost.Start();
Console.WriteLine($"Nancy now listening on {uri}.\n\nPress any key to exit");
Logger.LogInfo($"Nancy now listening on {uri}...");
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
Console.WriteLine("Error " + ex.Message + "\n\nPress any key to exit");
}
Console.ReadKey();
Logger.LogInfo("NancyDataService stopped...");
}
}
Now I want to make it a Windows Service. First try is with Topshelf. The following Main code is basically taken from Topshelf documentation and other articles about Topshelf.
static void Main(string[] args)
{
Logger.LogInfo("NancyDataService starting...");
var rc = HostFactory.Run(x =>
{
x.Service<DataService>(s =>
{
s.ConstructUsing(name => new DataService());
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});
x.RunAsLocalSystem();
x.StartAutomatically();
x.EnableServiceRecovery(r => r.RestartService(TimeSpan.FromSeconds(10)));
x.SetServiceName("NancyDataService");
});
var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode()); //11
Environment.ExitCode = exitCode;
}
Here is my DataService class, basically built from the Topshelf docs and a couple of articles I found:
class DataService
{
public DataService()
{
}
private SemaphoreSlim _semaphoreToRequestStop;
private Thread _thread;
public void Start()
{
// start Nancy here
var uri = new Uri(ConfigurationManager.AppSettings["uri"]);
var hostConfig = new HostConfiguration();
hostConfig.UrlReservations.CreateAutomatically = true;
hostConfig.RewriteLocalhost = false;
using var nancyHost = new NancyHost(uri, new AppBootstrapper(), hostConfig);
try
{
nancyHost.Start();
Console.WriteLine($"Nancy now listening on {uri}...");
Logger.LogInfo($"Nancy now listening on {uri}...");
// spin thread here
_semaphoreToRequestStop = new SemaphoreSlim(0);
_thread = new Thread(DoWork);
_thread.Start();
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
Console.WriteLine($"Error: {ex.Message}");
}
}
private void DoWork(object obj)
{
while (true)
{
Console.WriteLine("doing work..");
if (_semaphoreToRequestStop.Wait(500))
{
Console.WriteLine("Stopped");
break;
}
}
}
public void Stop()
{
Logger.LogInfo("NancyDataService stopping...");
_semaphoreToRequestStop.Release();
_thread.Join();
//return true;
}
}
So now when I run the project in design mode (which Topshelf says you should be able to do), it seems to start fine and Nancy seems to be listening on the right port. However, when I go to the browser and type in HTTP//localhost:8080/, I get "This site can't be reached. localhost refused to connect"
I have the latest version of Topshelf (4.2.1) and Topshelf.Log4Net packages.
Can anyone shed any light on this? Thanks...
Solved this issue. Turned out to be incorrect scoping of my NancyHost object. Works fine now.
I'm building a desktop APP using windows forms that needs to be authenticated via a WebAPI using Token authentication.
The API is proved that work because a mobile APP is using it and also I can get results using POSTMAN
The problem is when I'm calling the Authentication method from the desktop App.
When I do the request, the API recieves it and it only goes until ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context), not reaching GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) in the Auth process.
Here is my CustomAuthProvider
public class CustomOAuthProvider : OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return Task.FromResult<object>(null);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var allowedOrigin = "*";
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "El nombre de usuario o contraseña son incorrectos");
return;
}
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT");
var ticket = new AuthenticationTicket(oAuthIdentity, null);
context.Validated(ticket);
}
}
Here is my Startup class
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
HttpConfiguration httpConfig = new HttpConfiguration();
ConfigureOAuthTokenGeneration(app);
ConfigureOAuthTokenConsumption(app);
ConfigureWebApi(httpConfig);
}
}
At the moment I'm trying two different ways to authenticate the APP.
First One:
public LoginResponseModel Authenticate(LoginRequestModel applicationUser)
{
using (var client = new WebClient())
{
try
{
client.Headers["Content-Type"] = "application/json";
var data = applicationUser.Serialize();
var response = client.UploadString(Context.ApiUrl + "Authenticate","POST", JsonConvert.SerializeObject(applicationUser));
var resultJson = JsonConvert.DeserializeObject<LoginResponseModel>(response);
return resultJson;
}
catch (Exception exception)
{
}
}
return null;
}
And second one:
public async Task<ApplicationUser> Authenticate(LoginRequestModel applicationUser)
{
var client = new HttpClient();
try
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var data = applicationUser.Serialize();
var response = await client.PostAsJsonAsync(Context.ApiUrl + "Authenticate",data );
// return null by default (test)
return null;
}
catch (Exception exception)
{
}
return null;
}
And this is the model I'm using for the request
public class LoginRequestModel
{
public string Grant_type { get; set; } = "Password";
public string UserName { get; set; }
public string Password { get; set; }
}
And this should be the response:
public class LoginResponseModel
{
public string Access_token { get; set; }
public string Token_type { get; set; }
public string Expires_in { get; set; }
}
Ah the moment both ways of calling the API only reach the initial verification of the owin process (ValidateClientAuthentication). What can be happening? How I can fix this? What I need to do to make the process go to GrantResourceOwnerCredentials?
thanks for the help
I solved my problem. The problem was that the form wasn't being filled and sent correctly.
private AuthToken GetAuthToken(LoginRequestModel applicationUser)
{
using (var client = new HttpClient())
{
var form = new Dictionary<string, string>
{
{"grant_type", "password"},
{"username", applicationUser.UserName},
{"password", applicationUser.Password},
};
try
{
var tokenResponse = client.PostAsync(Context.ApiUrl + "Authenticate", new FormUrlEncodedContent(form)).Result;
var token = tokenResponse.Content.ReadAsAsync<AuthToken>(new[] { new JsonMediaTypeFormatter() }).Result;
return token;
}
catch (Exception e)
{
Log4Net.log.Error("Error Getting Auth token", e);
return null;
}
}
}
I want to execute a method periodically, this method get informations from database it show it into a label, I tried the following code :
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//update information
miseAjour();
}
}, 0, 2000);
when i run the main program, the background service run also normaly but when the informations changes on db i get this exception:
Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
And this is the code of method miseAjour :
public void miseAjour(){
try {
dbConnection db = new dbConnection();
Connection connect = db.connectiondb();
connect.setAutoCommit(false);
Statement stmt= connect.createStatement();
ResultSet rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
int nbrAderent = rs.getInt("nbrAderent");
rs.close();
stmt.close();
connect.commit();
connect.close();
main_nbrAdrTot.setText(nbrAderent + "");
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
}
You can Timer for this, but I would recommend to use the JavaFX provided API called as ScheduledService.
ScheduledService is made to execute the same Task at regular intervals and since it creates a Task internally, there are API which help you to bind the value to the UI controls.
ScheduledService<Object> service = new ScheduledService<Object>() {
protected Task<Object> createTask() {
return new Task<Object>() {
protected Object call() {
// Call the method and update the message
updateMessage(miseAjour());
return object; // Useful in case you want to return data, else null
}
};
}
};
service.setPeriod(Duration.seconds(10)); //Runs every 10 seconds
//bind the service message properties to your Label
label.textProperty().bind(service.messageProperty()); // or use your label -> main_nbrAdrTot
Inside the dbcall method miseAjour, return the value that you have fetched and you want to update the label with :
public String miseAjour(){
String nbrAderent = null;
try {
dbConnection db = new dbConnection();
Connection connect = db.connectiondb();
connect.setAutoCommit(false);
Statement stmt= connect.createStatement();
ResultSet rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
nbrAderent = String.valueOf(rs.getInt("nbrAderent"));
connect.commit();
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
rs.close();
stmt.close();
connect.close();
}
return nbrAderent;
}
Finnaly i resolved the problem ,here is the code :
public class TimerServiceApp {
public void start() throws Exception {
TimerService service = new TimerService();
service.setPeriod(Duration.seconds(10));
service.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent t) {
main_nbrAdrTot.setText(t.getSource().getMessage());
}
});
service.start();
}
private class TimerService extends ScheduledService<Integer> {
private final StringProperty nbrTotAderent = new SimpleStringProperty();
public final void setTotalAderentNumber(String value ) {
nbrTotAderent.set(value);
}
public String getTotalAderentNumber() throws SQLException {
String nbrAderent = null;
ResultSet rs=null;
Statement stmt=null;
Connection connect=null;
try {
dbConnection db = new dbConnection();
connect = db.connectiondb();
connect.setAutoCommit(false);
stmt= connect.createStatement();
rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
nbrAderent = String.valueOf(rs.getInt("nbrAderent"));
connect.commit();
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
rs.close();
stmt.close();
connect.close();
}
System.out.println(" Total aderent number updated to :" + nbrAderent + " Aderents ");
return nbrAderent;
}
protected Task<Integer> createTask() {
return new Task<Integer>() {
protected Integer call() throws SQLException {
nbrTotAderent.setValue(getTotalAderentNumber());
updateMessage(getTotalAderentNumber());
return Integer.parseInt(getTotalAderentNumber());
}
};
}
}
} `
and i called this service by :
TimerServiceApp s = new TimerServiceApp();
s.start();
i dont know if the solution is optimised but it work :) thank you #ItachiUchiha i took the solution from yout answer in the following link
In my Mainpage.xaml.cs file I have a function that creates an instance of another class and tries to download a webpage using a HttpWebRequest from that instance. The problem is, once I've managed to download the webpage I can't send it back to the main UI thread. I've tried using Deployment.Current.Dispatcher.BeginInvoke to send the webpage back to a TextBlock I have waiting, but when I try I get an error telling me that I can't access the TextBlock from the other class. Is there any way to pass data between two threads without using LocalStorage?
EDIT: code below:
MainPage:
private void button1_Click(object sender, RoutedEventArgs e)
{
Member m = new Member(name, id);
}
Member class:
public Member(String Member, String API)
{
APIKey = API;
MemberName = Member;
this.super = super;
DoSend(method, string, "", null);
}
public void DoSend(string method, string url, string body, string mimetype)
{
if (WebRequest.RegisterPrefix("https://",System.Net.Browser.WebRequestCreator.ClientHttp)) {
HttpWebRequest request = WebRequest.Create(makeURI(url)) as HttpWebRequest;
request.Method = method;
request.Headers["X-NFSN-Authentication"] = MakeAuthHeader(url,body);
if (body != "")
{
byte[] bodyData = Encoding.UTF8.GetBytes(body);
request.ContentType = mimetype;
//Stuff Should Happen Here
}
else
doStuff(request);
}
public void doStuff(HttpWebRequest httpReq)
{
httpReq.BeginGetResponse(r =>
{
var httpRequest = (HttpWebRequest)r.AsyncState;
var httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(r);
using (var reader = new StreamReader(httpResponse.GetResponseStream()))
{
var response = reader.ReadToEnd();
ResponseBlock.Text = response; //Invalid cross-thread reference
}
}, httpReq);
}
MainPage:
customClass.DownloadPage((result) =>
{
textBlock.Text = result;
},
(exception) =>
{
MessageBox.Show(exception.Message);
});
CustomClass:
public void DownloadPage(Action<string> callback, Action<Exception> exception)
{
WebClient webClient = new WebClient();
webClient.DonwloadStringCompleted += (s, e) =>
{
if (e.Error == null)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
callback(e.Result);
});
}
else
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
exception(e.Error);
});
}
};
webClient.DonwloadStringAsync();
}