Is it possible to create a function that returns a custom stream and handles it like this?
user.logIn('owner', '1234')
.listen(
success (Object user) {
print(user);
},
error: (Object user, Object error) {
print(error);
}
);
Something like:
class LoginResult {
bool success = false;
String username;
}
Stream<LoginResult> onLogin() async* {
while(...) {
yield new LoginResult()
..success = isSuccess
..userName = 'someUser';
}
}
or
StreamController<LoginResult> onLoginController = new StreamController<LoginResult>();
// might not be necessary if you only need one listener at most
Stream<LoginResult> _onLogin = onLoginController.stream.asBroadcastStream();
Stream<LoginResult> get onLogin => _onLogin
...
onLoginController.add(new LoginResult()
..success = isSuccess
..userName = 'someUser');
Then you can use it like
Related
I have the following code
#Injectable()
export class ReceptionService {
private generalInfoDataSrc$ = new BehaviorSubject<any>(null);
public generalInfoData = this.generalInfoDataSrc$.asObservable();
setGeneralInfo(dataSrc: GeneralInfoMModal) {
this.generalInfoDataSrc$.next(dataSrc);
}
}
From my component1 I will set the above as
OnSelect(patient: any) {
let generalInfo = new GeneralInfoMModal();
generalInfo.id = patient.id;
// some other code here
// this.recepService.setGeneralInfo(generalInfo);
}
// from component2
//
ngOnInit() { getPatientDetails() }
getPatientDetails() {
this.receptionService.generalInfoData.pipe(mergeMap(response => {
if (response && response.id) {
this.loading = true;
return this.receptionService.get('User/Get' + response.id, this.sourceobj);
} else {
return of(null);
}
}), takeUntil(this.unsubscribe$)).subscribe(response => {
this.patient = response;
this.loading = false;
}, error => {
this.loading = false;
// this.utility.showMsg('An error occurred while getting user.')
}, () => {
})
}
Every things works well. I keep on selecting a user thereby calling the User/Get api. But if in case if the api returns an error then error part is executed after which when there is a change in behaviorsubject(user is selected) it doesn't call the User/Get. Is there other way of handling errors with behaviorsubject or any other approach to handle the idea. How a behaviorsubject should be used in such a case.
If you are using the same behavior subject over and over again, and if there is an error, you need to set the behavior subject back to null, so that when the next user is set, it will get the latest value.
Try something like this:
getPatientDetails() {
this.receptionService.generalInfoData.pipe(mergeMap(response => {
if (response && response.id) {
this.loading = true;
return this.receptionService.get('User/Get' + response.id, this.sourceobj);
} else {
return of(null);
}
}), takeUntil(this.unsubscribe$)).subscribe(response => {
this.patient = response;
this.loading = false;
}, error => {
this.loading = false;
///////////////////////////////// ADD THIS LINE ///////////////////////
this.recepService.setGeneralInfo(null);
// this.utility.showMsg('An error occurred while getting user.')
}, () => {
})
I have a function called LoginWithFb(). The function has a try catch block:
void loginWithFb() async {
try {
var auth = AuthProvider.of(context).auth;
print('Signing up with fb...');
setState(() {
_showProgressIndicator = true;
});
FirebaseUser user = await auth.signInWithFBAcc();
uId = user?.uid;
if (uId != null) {
print('Signed in: $uId');
widget.onSignedIn(user);
} else {
print('fb login cancelled');
}
// _showAlert(context);
setState(() {
_showProgressIndicator = false;
});
} catch (exception) {
print(exception.toString());
setState(() {
_showProgressIndicator = false;
});
}
When the error is caught, I want to display message to the user. The message has to be in a text field and not via a dialog. At the moment I have an empty Text('') widget in my build method. I want to write text to the text widget when the error is caught..
Just use local variable for storing message and show it via Text widget
String message = "";
void loginWithFb() async {
try {
...
} catch (exception) {
print(exception.toString());
setState(() {
message = "Some error happens";
_showProgressIndicator = false;
});
}
In widget:
Text(message);
When Saving schedule to calendar it must auto update the activity logs on my notification bar in my Home Controller. It saves the data but only show when notification bar is refreshed. It seems that Hub is not starting when saved.
CalendarController.cs
[HttpPost]
public JsonResult SaveSchedule(Schedule s)
{
var userid = User.Identity.GetUserId();
var profile = _context.Profiles.Single(p => p.Id == userid);
var status = false;
if (s.Schedule_ID > 0)
{
//Update
var v = _context.Schedules.Where(a => a.Schedule_ID == s.Schedule_ID).FirstOrDefault();
if (v != null)
{
v.Shift = s.Shift;
}
}
var activitylog = new ActivityLog
{
UserId = userid,
LogDate = DateTime.Now,
Activity = ActivityHelper.GetActivityLog(4, profile.FirstName)
};
// save to data and must be shown on notification bar
_context.ActivityLogs.Add(activitylog);
_context.SaveChanges();
ActivityHub.StartLogging();
status = true;
return new JsonResult { Data = new { status = status } };
}
HomeController.cs
public JsonResult GetLogs()
{
return Json(ActivityHelper.GetActivityLogs(), JsonRequestBehavior.AllowGet);
}
ActivityHub.cs
public class ActivityHub : Hub
{
public static void StartLogging()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<ActivityHub>();
//calls the signalR client part to execute javascript method
context.Clients.All.displayLog();
}
}
My CSHTML
<script>
$(function () {
var activityFromHub = $.connection.activityHub;
$.connection.hub.start().done(function () {
FetchLogs();
});
activityFromHub.client.displayLog = function () {
console.log('Hub Started');
FetchLogs();
}
function FetchLogs() {
$.ajax({
type: 'GET',
url: '/Home/GetLogs',
datatype: 'json',
success: function (data) {
$("#logs tr").remove();
data = $.parseJSON(data);
if (data.length > 0) {
.... do some append here
}
},
error: function (error) {
alert("error");
}
});
}
});
</script>
ActivityHelper.cs
static readonly string connString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
public static class ActivityHelper
{
public static string GetActivityLogs()
{
string sqlCommand = #"my select query here";
try
{
var messages = new List<ActivityLog>();
using(var connection = new SqlConnection(connString))
{
connection.Open();
using (SqlConnection con = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(sqlCommand, con);
if(con.State != System.Data.ConnectionState.Open)
{
con.Open();
}
cmd.Notification = null;
SqlDependency dependency = new SqlDependency(cmd);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
var reader = cmd.ExecuteReader();
while (reader.Read())
{
messages.Add(item: new ActivityLog
{
Activity = reader["Activity"] != DBNull.Value ? (string)reader["Activity"] : "",
LogDate = (DateTime)reader["LogDate"]
});
}
}
}
var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(messages);
return json;
}
catch(Exception ex)
{
throw;
}
}
public static void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
SqlDependency dependency = sender as SqlDependency;
dependency.OnChange -= dependency_OnChange;
var activityHub = GlobalHost.ConnectionManager.GetHubContext<ActivityHub>();
GetActivityLogs();
}
}
}
FIRST METHOD
First Solution change your javascript code like this. If this not works move to the second method:
$(function () {
var activityFromHub = $.connection.ActivityHub;
$.connection.hub.start().done(function () {
FetchLogs();
});
activityFromHub.client.displayLog = function () {
console.log('Hub Started');
FetchLogs();
}
});
SECOND METHOD:
Each client connecting to a hub passes a unique connection id. You can retrieve this value in the Context.ConnectionId property of the hub context. And i found there is nothing happening like this. You may try this solution.
I think the simplest solution for your question is to use groups.
http://www.asp.net/signalr/overview/guide-to-the-api/working-with-groups
Your hub class would contain methods to join a group:
public Task JoinGroup(string groupName)
{
return Groups.Add(Context.ConnectionId, groupName);
}
public Task LeaveGroup(string groupName)
{
return Groups.Remove(Context.ConnectionId, groupName);
}
and your hub will be look like this:
public static void StartLogging(string groupName)
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<ActivityHub>();
context.Clients.Group(groupName).displayLog();
//calls the signalR client part to execute javascript method
//context.Clients.All.displayLog();
}
And change your javascript as like this:
$(function () {
var activityFromHub = $.connection.ActivityHub;
$.connection.hub.start().done(function () {
activityFromHub.server.joinGroup("Group1");
activityFromHub.server.StartLogging("Group1");
FetchLogs();
});
activityFromHub.client.displayLog = function () {
console.log('Hub Started');
FetchLogs();
}
});
I hope this will resolve your issue. If you are still facing issue. Please leave comments. Thank you.
Here's my Angular controller
//Save And Update
$scope.AddUpdateBusinessType = function() {
var businessType = {
Code: $scope.businessCode,
BusiType: $scope.businessType
};
var getBusinessTypeAction = $scope.BusinessTypeAction;
if (getBusinessTypeAction == "Update") {
businessType.BusinessTypeId = $scope.businessTypeId;
var getBusinessTypeData = businessTypeService.updateBusinessType(businessType);
getBusinessTypeData.then(function (msg) {
GetAllBusinessType();
$scope.ClearBusinessTypeForm();
alert("Record Updated Successful");
$scope.BusinessTypeAction = "";
$scope.divBusinessType = false;
}, function () {
alert('Error in Updating Record');
});
} else {
**// Save Section**
var getExistBusinessCode = businessTypeService.checkBusinessTypeCode(businessType.Code);
getExistBusinessCode.then(function (businessTypeCode) {
debugger;
if (businessTypeCode == true) {
alert('Business Type Code Already Exist');
} else {
debugger;
var getBusinessTypeData = businessTypeService.addBusinessType(businessType);
getBusinessTypeData.then(function (msg) {
GetAllBusinessType();
$scope.ClearBusinessTypeForm();
alert("Record Added Successful");
$scope.divBusinessType = false;
}, function () {
alert("Error Occured In Saving Data");
});
}
},function() {
alert('Error Occured While Checking Records');
});
}
}
In the above code Save Section I am trying to check if a value is exists in a database so I'm passing a string value to: checkBusinessTypeCode(businessType.Code) Service.When I Debug and See Value its Seems Normal.
Here's My Service:
//Check Business Code
this.checkBusinessTypeCode = function (businessTypeCode) {
debugger;
var response = $http({
method: "post",
url: "/BusinessType/CheckBusinessTypeDetailByCode",
params: {
businessTypeCode: JSON.stringify(businessTypeCode)
}
});
return response;
}
But when Passing To Controller string value I get some unexpected behavior.
two \\ always appear automatically
example
"\"stringvalue\""
I'm Still Having Above Problem
but as a quick solution i did code as follows
public bool _CheckBusinessTypeDetailByCode(string businessTypeCode)
{
string bisCode = businessTypeCode.Replace("\"", "");
bool isExist;
isExist = _IBusinessTypeRepository.IsExist(x => x.IsActive && !x.IsDelete && x.Code == bisCode);
return isExist;
}
I don't know is it bad practice or not , any way it is solved my problem.
Before did this modification
string businessTypeCode always gives value as
"\"somevalue\""
Is it possible to check if any errors has been logged to a ILogger in Serilog?
var log = new LoggerConfiguration().CreateLogger();
SomeAlgorithm(log);
// How can I check if an error was logged?
A custom sink can do this, in a few lines of code.
class ErrorDetector : ILogEventSink {
volatile bool _errorDetected;
public bool ErrorDetected { get { return _errorDetected; } }
public void Emit(LogEvent evt) {
if (evt.Level == LogEventLevel.Error ||
evt.Level == LogEventLevel.Fatal) {
_errorDetected = true;
}
}
}
Then:
var detector = new ErrorDetector();
var log = new LoggerConfiguration()
.WriteTo.Sink(detector)
.CreateLogger();
// Later
if (detector.ErrorDetected) { ...