I've only just started looking a profiling for an MVC3 application.
I found MiniProfiler first, and then found recommendations for using Glimpse. Both seem great, and I'd rather use Glimpse, but I'd like to add entries to the timeline for specific actions.
MiniProfiler has a nice feature where you can grab the current MiniProfiler context and add a step with the using() command. Is there a similar thing with Glimpse?
I did find an entry with someone explaining how to do it the long way, but wondered if there might have been a shorter way to do this, since then.
Thanks to this stackoverflow question, I found a gist that implements an equivalent of Glimpse v2's GlimpseTimeline for Glimpse v1.
From your code call:
using (Timeline.Capture("FormulaEvaluator.Evalauate"))
{
// Code to time
}
And here's the implementation of Timeline.Capture:
public static class Timeline
{
public static IDisposable Capture(string eventName)
{
#pragma warning disable 618
var timer = GlimpseConfiguration.GetConfiguredTimerStrategy()();
if (timer == null)
return null;
var broker = GlimpseConfiguration.GetConfiguredMessageBroker();
if (broker == null)
return null;
#pragma warning restore 618
return new TimelineCapture(timer, broker, eventName);
}
}
public class TimelineCapture : IDisposable
{
private readonly string _eventName;
private readonly IExecutionTimer _timer;
private readonly IMessageBroker _broker;
private readonly TimeSpan _startOffset;
public TimelineCapture(IExecutionTimer timer, IMessageBroker broker, string eventName)
{
_timer = timer;
_broker = broker;
_eventName = eventName;
_startOffset = _timer.Start();
}
public void Dispose()
{
_broker.Publish(new TimelineMessage(_eventName, _timer.Stop(_startOffset)));
}
}
public class TimelineMessage : ITimelineMessage
{
private static readonly TimelineCategoryItem DefaultCategory = new TimelineCategoryItem("MyApp", "green", "blue");
public TimelineMessage(string eventName, TimerResult result)
{
Id = Guid.NewGuid();
EventName = eventName;
EventCategory = DefaultCategory;
Offset = result.Offset;
StartTime = result.StartTime;
Duration = result.Duration;
}
public Guid Id { get; private set; }
public TimeSpan Offset { get; set; }
public TimeSpan Duration { get; set; }
public DateTime StartTime { get; set; }
public string EventName { get; set; }
public TimelineCategoryItem EventCategory { get; set; }
public string EventSubText { get; set; }
}
The Google group thread you mentioned is currently the approach that is being developed in version-2 of Glimpse. There you can find the GlimpseTimeline class that does what you want.
You could take this class and copy it in your own project while waiting for v2 to be released. Just keep in mind that you need to alter it a little bit, as some things like the MessageBroker are to be retrieved from the GlimpseConfiguration.GetConfiguredMessageBroker() etc...
But it might suit your needs for now...
I made a mashup of droyads gist and GlimpseTimeline from v2. GlimpseTimeline v1 gist
public class TimelineMessage : ITimelineMessage
{
public TimelineMessage()
{
Id = Guid.NewGuid();
}
public Guid Id { get; private set; }
public TimeSpan Offset { get; set; }
public TimeSpan Duration { get; set; }
public DateTime StartTime { get; set; }
public string EventName { get; set; }
public TimelineCategoryItem EventCategory { get; set; }
public string EventSubText { get; set; }
}
public static class GlimpseTimeline
{
private static readonly TimelineCategoryItem DefaultCategory = new TimelineCategoryItem( "User", "green", "blue" );
public static OngoingCapture Capture( string eventName )
{
return Capture( eventName, null, DefaultCategory, new TimelineMessage() );
}
public static OngoingCapture Capture( string eventName, string eventSubText )
{
return Capture( eventName, eventSubText, DefaultCategory, new TimelineMessage() );
}
internal static OngoingCapture Capture( string eventName, TimelineCategoryItem category )
{
return Capture( eventName, null, category, new TimelineMessage() );
}
internal static OngoingCapture Capture( string eventName, TimelineCategoryItem category, ITimelineMessage message )
{
return Capture( eventName, null, category, message );
}
internal static OngoingCapture Capture( string eventName, ITimelineMessage message )
{
return Capture( eventName, null, DefaultCategory, message );
}
internal static OngoingCapture Capture( string eventName, string eventSubText, TimelineCategoryItem category, ITimelineMessage message )
{
if (string.IsNullOrEmpty( eventName ))
{
throw new ArgumentNullException( "eventName" );
}
#pragma warning disable 618
var executionTimer = GlimpseConfiguration.GetConfiguredTimerStrategy()();
var messageBroker = GlimpseConfiguration.GetConfiguredMessageBroker();
#pragma warning restore 618
if (executionTimer == null || messageBroker == null)
{
return OngoingCapture.Empty();
}
return new OngoingCapture( executionTimer, messageBroker, eventName, eventSubText, category, message );
}
public static void CaptureMoment( string eventName )
{
CaptureMoment( eventName, null, DefaultCategory, new TimelineMessage() );
}
public static void CaptureMoment( string eventName, string eventSubText )
{
CaptureMoment( eventName, eventSubText, DefaultCategory, new TimelineMessage() );
}
internal static void CaptureMoment( string eventName, TimelineCategoryItem category )
{
CaptureMoment( eventName, null, category, new TimelineMessage() );
}
internal static void CaptureMoment( string eventName, TimelineCategoryItem category, ITimelineMessage message )
{
CaptureMoment( eventName, null, category, message );
}
internal static void CaptureMoment( string eventName, ITimelineMessage message )
{
CaptureMoment( eventName, null, DefaultCategory, message );
}
internal static void CaptureMoment( string eventName, string eventSubText, TimelineCategoryItem category, ITimelineMessage message )
{
if (string.IsNullOrEmpty( eventName ))
{
throw new ArgumentNullException( "eventName" );
}
#pragma warning disable 618
var executionTimer = GlimpseConfiguration.GetConfiguredTimerStrategy()();
var messageBroker = GlimpseConfiguration.GetConfiguredMessageBroker();
#pragma warning restore 618
if (executionTimer == null || messageBroker == null)
{
return;
}
message
.AsTimelineMessage( eventName, category, eventSubText )
.AsTimedMessage( executionTimer.Point() );
messageBroker.Publish( message );
}
public class OngoingCapture : IDisposable
{
public static OngoingCapture Empty()
{
return new NullOngoingCapture();
}
private OngoingCapture()
{
}
public OngoingCapture( IExecutionTimer executionTimer, IMessageBroker messageBroker, string eventName, string eventSubText, TimelineCategoryItem category, ITimelineMessage message )
{
Offset = executionTimer.Start();
ExecutionTimer = executionTimer;
Message = message.AsTimelineMessage( eventName, category, eventSubText );
MessageBroker = messageBroker;
}
private ITimelineMessage Message { get; set; }
private TimeSpan Offset { get; set; }
private IExecutionTimer ExecutionTimer { get; set; }
private IMessageBroker MessageBroker { get; set; }
public virtual void Stop()
{
var timerResult = ExecutionTimer.Stop( Offset );
MessageBroker.Publish( Message.AsTimedMessage( timerResult ) );
}
public void Dispose()
{
Stop();
}
private class NullOngoingCapture : OngoingCapture
{
public override void Stop()
{
}
}
}
}
Related
I do not have much code here
But I want to create my own validation for username that will not have duplicates.
Model:
[Table("User")]
public partial class User
{
[Key]
public Guid Id { get; set; } = Guid.NewGuid();
[Column("userName")]
[StringLength(200)]
[AllValidation(ErrorMessage = "foo")]
[Required(ErrorMessage = "Username is a required field")]
public string UserName { get; set; } = null!;
[StringLength(50, MinimumLength = 3, ErrorMessage = "The password should be between 3 characters to 50")]
[Required(ErrorMessage = "Password is a required field")]
public string Password { get; set; } = null!;
//[Column(TypeName = "date")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy/MM/dd}")]
public DateTime? LastLogin { get; set; }
public string? Token { get; set; }
}
ValidationAttribute:
public class AllValidationAttribute : ValidationAttribute
{
private readonly TalkBackDbContext _context;
public AllValidationAttribute(TalkBackDbContext context)
{
_context = context;
}
public override string FormatErrorMessage(string name)
{
return _context.Users.SingleOrDefault(x => x.UserName == name)!.ToString()!;
}
}
I get an error when I try to insert ErrorMessage into an attribute
this is the error:
you can do this.
remove it from constructor and override IsValid method.
public class AllValidationAttribute : ValidationAttribute
{
private string username;
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
var _context = (TalkBackDbContext )validationContext
.GetService(typeof(TalkBackDbContext ));
username = value.ToString();
if(!_context.Users.Any(cus => cus.UserName == value.ToString()))
{
return ValidationResult.Success;
}
else
{
return new ValidationResult
("Unique Name expected" + value.ToString());
}
}
public override string FormatErrorMessage(string name)
{
return "Expected Uniquename" + username;
}
}
I tried to implement the function without success
I want to check if the user's status is true so that means he is logged in
I mean if Status is false then I do not want to display it at all in a list that will be ignored
What I tried causes all the connected to be displayed even if they are false
Model:
[Table("Contact")]
public partial class Contact
{
[Key]
public Guid Id { get; set; }
public string DisplayName { get; set; } = null!;
public string ProfilePic { get; set; } = null!;
public int? Rating { get; set; }
public bool? Status { get; set; }
public bool? IsRegistration { get; set; }
}
DbContext:
public virtual DbSet<Contact> Contacts { get; set; } = null!;
Repository:
private readonly TalkBackContactsDbContext _context;
public ContactsRepository(TalkBackContactsDbContext context)
{
_context = context;
}
public IQueryable<Contact> GetAllConnectedUser(Contact contact)
{
if (contact.Status == false)
{
throw new Exception("Not exist");
}
else
{
return _context.Contacts;
}
}
api controller:
private readonly IContactsRepository _repo;
public ContactsController(IContactsRepository repo)
{
_repo = repo;
}
[HttpGet()]
public IEnumerable<Contact> GetAllConnected()
{
var contact = new Contact();
try
{
return _repo.GetAllConnectedUser(contact);
}
catch (Exception e)
{
e.ToString();
}
return _repo.GetAllConnectedUser(contact);
}
Try this.
Repository:
private readonly TalkBackContactsDbContext _context;
public ContactsRepository(TalkBackContactsDbContext context)
{
_context = context;
}
public IEnumerable<Contact> GetAllConnectedUser()
{
_context.Contacts.Where(a=>a.Status==true).AsEnumerable();
}
api controller:
private readonly IContactsRepository _repo;
public ContactsController(IContactsRepository repo)
{
_repo = repo;
}
[HttpGet()]
public IEnumerable<Contact> GetAllConnected()
{
return _repo.GetAllConnectedUser();
}
I need to catch the exception form my custom model attribute on validating it.
Here is my HttpStatusCodeExceptionMiddleware:
public class HttpStatusCodeExceptionMiddleware
{
private readonly RequestDelegate _next;
public HttpStatusCodeExceptionMiddleware(RequestDelegate next)
{
_next = next ?? throw new ArgumentNullException(nameof(next));
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (HttpStatusCodeException ex)
{
if (context.Response.HasStarted)
{
throw;
}
context.Response.Clear(); //<-possible Angular CORS error
context.Response.StatusCode = ex.StatusCode;
context.Response.ContentType = ex.ContentType;
ProblemDetails responseBody = new ProblemDetails(ex.Message, ex.StatusCode, "Request error", ex.Key);
await context.Response.WriteAsync(JsonConvert.SerializeObject(responseBody));
return;
}
}
public class HttpStatusCodeException : Exception
{
public int StatusCode { get; set; }
public string ContentType { get; set; } = #"text/plain";
//key for translation
public string Key { get; set; }
public HttpStatusCodeException(HttpResponseType statusCode)
{
this.StatusCode = (int)statusCode;
}
public HttpStatusCodeException(HttpResponseType statusCode, string message, string key) : base(message)
{
StatusCode = (int)statusCode;
Key = key;
}
public HttpStatusCodeException(HttpResponseType statusCode, Exception inner, string key) : base(inner.ToString())
{
Key = key;
}
public HttpStatusCodeException(HttpResponseType statusCode, JObject errorObject, string key) : this(statusCode, errorObject.ToString(), key)
{
this.ContentType = #"application/json";
}
}
public static class HttpStatusCodeExceptionMiddlewareExtensions
{
public static IApplicationBuilder UseHttpStatusCodeExceptionMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<HttpStatusCodeExceptionMiddleware>();
}
}
And I am using it in the Startup.cs Configure method like this:
app.UseHttpStatusCodeExceptionMiddleware();
But in this scenario I need to catch the model attribute validation exception, but my solution only catches the controller exceptions.
Is there a way to do it?
thnx
You need to throw a HttpStatusCodeException then you could hit the catch (HttpStatusCodeException ex):
1.Custom validation attribute:
public class TestNameAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
if (value.ToString().StartsWith("a"))
{
throw new HttpStatusCodeException(HttpStatusCode.BadRequest, "Name could not start with a", value.ToString());
//return new ValidationResult("Name could not start with a");
}
return ValidationResult.Success;
}
}
2.Model:
public class YourModel
{
public long Id { get; set; }
[TestName]
public string Name { get; set; }
public string DisplayName { get; set; }
}
3.Test action:
[HttpPost]
public async Task<ActionResult<Mood>> Post(YourModel model)
{
_context.YourModel.Add(model);
await _context.SaveChangesAsync();
return CreatedAtAction("Get", new { id = model.Id }, model);
}
I have an application that allows users to log in via facebook. I am trying to save each user to my database using my WebApi. However, I am encountering this exception error: System.NullReferenceException: Object reference not set to an instance of an object. Can anyone see what I am doing incorrectly to cause this. Thanks.
CustomerService class:
public async Task<int> AddCustomer(Customer cust)
{
var data = JsonConvert.SerializeObject(cust);
var content = new StringContent(data, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Add("X-Giftworx-App", "Posworx");
var response = await client.PostAsync("http/my api address/api/Customer/Insert", content);
var result = JsonConvert.DeserializeObject<int>(response.Content.ReadAsStringAsync().Result);
return result;
}
Customer class:
public class Customer
{
public string Token { get; set; }
public bool Authenticated { get; set; }
public string SecretKey { get; set; }
public int StoreCustomerID { get; set; }
public string Number { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public object Address { get; set; }
public string Email { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string Country { get; set; }
public string MobilePhone { get; set; }
public DateTime DOB { get; set; }
public object Phone { get; set; }
public object DeviceToken { get; set; }
public object Details { get; set; }
public object Gender { get; set; }
public bool IsError { get; set; }
public object ErrorMessage { get; set; }
public bool PhoneVerified { get; set; }
}
FacebookRender
public class FacebookRender : PageRenderer
{
CustomerService customerService;
public FacebookRender()
{
var activity = this.Context as Activity;
var auth = new OAuth2Authenticator(
clientId: "my app client's id",
scope: "",
authorizeUrl: new Uri("https://www.facebook.com/dialog/oauth/"),
redirectUrl: new Uri("https://www.facebook.com/connect/login_success.html")
);
auth.Completed += async (sender, eventArgs) =>
{
if (eventArgs.IsAuthenticated)
{
await AccountStore.Create().SaveAsync(eventArgs.Account, "FacebookProviderKey");
var accessToken = eventArgs.Account.Properties["access_token"].ToString();
var expiresIn = Convert.ToDouble(eventArgs.Account.Properties["expires_in"]);
var expiryDate = DateTime.Now + TimeSpan.FromSeconds(expiresIn);
var request = new OAuth2Request("GET", new Uri("https://graph.facebook.com/me"), null, eventArgs.Account);
var response = await request.GetResponseAsync();
var obj = JObject.Parse(response.GetResponseText());
var id = obj["id"].ToString().Replace("\"", "");
var name = obj["name"].ToString().Replace("\"", "");
Customer cust = new Customer();
cust.Token = accessToken;
cust.Name = name;
await customerService.AddCustomer(cust);
App.NavigateToProfile(string.Format(name));
}
else
{
App.NavigateToProfile("Invalid Login");
}
};
activity.StartActivity(auth.GetUI(activity));
}
}
i create two class in my model and create relation many to many by Entity
in sql my classes is created tables Properly
when i try to insert data in this table get show error "Object reference not set to an instance of an object." my cod is:
public class News
{
public int ID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime Date { get; set; }
public virtual Picture Picture { get; set; }
public virtual NewsType NewsType { get; set; }
public ICollection<Tag> Tag { get; set; }
public News(int id, string title, string content, DateTime date)
{
this.ID = id;
this.Title = title;
this.Content = content;
this.Date = date;
}
public News()
{
}
}
public class Tag
{
public int ID { get; set; }
public string Title { get; set; }
public ICollection<News> News { get; set; }
public Tag()
{
}
}
public class DatabaseContext : DbContext
{
public DatabaseContext()
: base("News")
{
}
static DatabaseContext()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<DatabaseContext>());
}
public DbSet<News> newsInfo { get; set; }
public DbSet<Picture> pictures { get; set; }
public DbSet<NewsType> Types { get; set; }
public DbSet<Tag> Tags { get; set; }
}
[HttpPost]
public ActionResult AddNews(NewsViewModel newsInfo)
{
using (Models.DatabaseContext dbContext = new DatabaseContext())
{
ViewData["Type"] = new SelectList(dbContext.Types.ToList(), "Id", "Title");
}
if (!ModelState.IsValid)
{
return View();
}
else
{
Models.DatabaseContext dbContext = new Models.DatabaseContext();
Models.News news = new Models.News();
news.Title = newsInfo.Title;
news.Content = newsInfo.Content;
news.Date = DateTime.Now;
string newsinput = newsInfo.Tag.cleanTag();
string[] tags = new string[] { };
if (newsinput != null)
{
tags = newsinput.Split(',');
}
foreach (string item in tags)
{
Tag findTag = dbContext.Tags.Where(x => x.Title == item).FirstOrDefault();
if (findTag != null)
{
news.Tag.Add(findTag)
////////////////////////show error in this line
}
}
news.NewsType = dbContext.Types.Find(Convert.ToInt32(Request.Form["rdb"]));
dbContext.newsInfo.Add(news);
dbContext.SaveChanges();
return View();
}