ASP.Net MVC 3 System.Data.SqlClient.SqlException Timeout expired - asp.net-mvc-3

I am developing an ASP.Net MVC 3 web application using Entity Framework 4.1. I recently uploaded the application to my test server and I have noticed an error email delivered by ELMAH stating
System.Data.SqlClient.SqlException Timeout expired. The timeout period
elapsed prior to completion of the operation or the server is not
responding.
Below shows some of my code.
Controller
public ActionResult VerifyEmail(int uid, string vid)
{
var userList = _userService.VerifyEmail(uid,vid).ToList();
}
Service
public IList<User> VerifyEmail(int uid, string emailvcode)
{
return _uow.User.Get(u => u.userID == uid && u.emailVerificationCode == emailvcode).ToList();
}
Unit of Work
public class UnitOfWork : IUnitOfWork, IDisposable
{
readonly LocumEntities _context = new LocumEntities();
private GenericRepository<User> _user = null;
public IGenericRepository<User> User
{
get
{
if (_user == null)
{
_user = new GenericRepository<User>(_context);
}
return _user;
}
}
}
Generic Repository
public IList<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
The Timeout error is sometimes happening when the line within the Service method is trying to execute
return _uow.User.Get(u => u.userID == uid && u.emailVerificationCode == emailvcode).ToList();
This error is not happening every time, only occasionally, however, I don't understand why as this query will either return a list of Users, or, a NULL list.
Can anyone spot from my code why this may be happening?
Any feedback would be appreciated as I have no idea why this is happening.
Thanks.

Try increasing the timeout property in the connection string. Also run the SQL Server Profiler to see how much SQL is being generated for your queries, as the query may be returning a large volume of data causing the timeout.

Related

Trouble sending a specific request with null parameters to an API

This is an example of the controller I've built in .Net Core 2.1.
[Route("api/TestApi")]
public class TestApiController: Controller
{
[HttpGet("{param1?}/{param2?}/{param3?}")]
//[HttpGet]
public ActionResult Get(int? param1 = null, DateTime? param2 = null, bool? param3 = null)
{
//Get data ...
}
}
My issue with this set up is that I cannot call this function with a null parameter;
This kind of call will not work: http://localhost:9000/api/TestApi/null/null/true. It will give me an error stating that null is not a valid input for param1.
Now I cannot rely on reading parameters from a query string (company constraints)
but I would like to point out that it does work if I use [HttpGet] instead and use the url parameters.
Any ideas? suggestions? questions?
All would be welcome.
Thanks in advance.
I found sort of a patch to use.
It involves adding a middle ware in Startup.cs file.
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = false;
options.InvalidModelStateResponseFactory = actionContext =>
{
if (
!string.IsNullOrEmpty(actionContext.ActionDescriptor.AttributeRouteInfo.Template)
&& actionContext.ActionDescriptor.AttributeRouteInfo.Template.Contains("?"))
{
//Hard coded removed bad error if template has int?/double?/datetime?
return null;
}
else
{
var errors = actionContext.ModelState
.Where(e => e.Value.Errors.Count > 0)
.Select(e => new Error
{
Name = e.Key,
Message = e.Value.Errors.First().ErrorMessage
}).ToArray();
return new BadRequestObjectResult(errors);
}
};
});
I have managed to finally use the URL I specified in the question;
http://localhost:9000/api/TestApi/null/null/true
Again, it's not a solid solution, just a workaround.

Caching in Automapper Resolver to increase performance

As follows, I m using auto mapper to convert tasks
Mapper.CreateMap<Task, GanttTask>().ForMember(dst => dst.parentIdRaw, opt => opt.ResolveUsing<TaskParentIdResolver>())
so in TaskParentIdResolver,
public class TaskParentIdResolver : ValueResolver<Task, int?>
{
protected IUow Uow { get; set; }
public TaskParentIdResolver()
{
RepositoryFactories factory = new RepositoryFactories();
IRepositoryProvider provider = new RepositoryProvider(factory);
this.Uow = new Uow(provider);
}
protected override int? ResolveCore(Task source)
{
if (source.ParentId != null && source.ParentId != Guid.Empty)
{
var task = Uow.Tasks.GetById(source.ParentId.Value);
return task.Id;
}
else return null;
}
}
The problem i faced is,
var tasksList = Mapper.Map<IEnumerable<Task>, IEnumerable<GanttTask>>(Uow.Tasks.GetAll().Where(con => con.IsProjectSummary == true)).ToList();
If i have 200 task then resolver called as 200 times and each time Uow takes time to return to resolve the parentId. Is there any way to cache this task list in resolver so that only first UOw calls the task and all the other times it returns the cache list of tasks.
Don't put caching in AutoMapper, put it in whatever service that AutoMapper uses. If you're using an ORM, use the caching available in the ORM.

Understanding Get Method Overrides

I am totally new to Web API an am not understanding how to Filter get calls.
This method returns all items in my database.
// GET: api/LogEntries
public IQueryable<LogEntry> GetLogEntries()
{
return db.LogEntries;
}
This method returns a specific item in my database.
// GET: api/LogEntries/5
[ResponseType(typeof(LogEntry))]
public IHttpActionResult GetLogEntry(int id)
{
LogEntry logEntry = db.LogEntries.Find(id);
if (logEntry == null)
{
return NotFound();
}
return Ok(logEntry);
}
So now I want to filter the returned records so I created this method but it won't work because the specific item method gets called. I seem to be missing a concept and am hoping you can point me to more clear understanding. Thanks
// GET: api/LogEntries
public IQueryable<LogEntry> GetLogEntries(string levelID)
{
int levIdInt;
if (Int32.TryParse(levelID, out levIdInt))
{
return db.LogEntries.Take(300).Where(l => (int)l.Level == levIdInt).OrderByDescending(d => d.TimeStamp);
}
return db.LogEntries.Where(i => i.ID < 0);
}
You need to specify the route for that method
[Route("api/LogEntries/Level/{levelID}"]
public IQueryable<LogEntry> GetLogEntries(string levelID)
{}
More on routing is available here http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

ServiceStack caching strategy

I'm learning ServiceStack and have a question about how to use the [Route] tag with caching. Here's my code:
[Route("/applicationusers")]
[Route("/applicationusers/{Id}")]
public class ApplicationUsers : IReturn<ApplicationUserResponse>
{
public int Id { get; set; }
}
public object Get(ApplicationUsers request)
{
//var cacheKey = UrnId.Create<ApplicationUsers>("users");
//return RequestContext.ToOptimizedResultUsingCache(base.Cache, cacheKey, () =>
return new ApplicationUserResponse
{
ApplicationUsers = (request.Id == 0)
? Db.Select<ApplicationUser>()
: Db.Select<ApplicationUser>("Id = {0}", request.Id)
};
}
What I want is for the "ApplicationUsers" collection to be cached, and the times when I pass in an Id, for it to use the main cached collection to get the individual object out.
If I uncomment the code above, the main collection is cached under the "users" key, but any specific query I submit hits the Db again. Am I just thinking about the cache wrong?
Thanks in advance,
Mike
this line
var cacheKey = UrnId.Create<ApplicationUsers>("users");
is creating the same cache key for all the requests, you must use some of the request parameters to make a "unique key" for each different response.
var cacheKey = UrnId.Create<ApplicationUsers>(request.Id.ToString());
this will give you the "urn:ApplicationUsers:0" key for the get all and the "urn:ApplicationUsers:9" for the request with Id = 9
now you can use the extension method in this way.
return RequestContext.ToOptimizedResultUsingCache(Cache, cacheKey, () => {
if(request.Id == 0) return GetAll();
else return GetOne(request.Id);
});
I hope this helps, regards.

How to best implement custom search on a Membership provider

Out of the box, System.Web.Security.Membership implements a couple of search methods:
FindUsersByEmail
FindUsersByName
I'm using the WSAT project from CodePlex to administer my Membership database. The tool implements extra profile properties in a ProfileCommon class.
Let's say I have a property called Firm in the user's profile.
I need to implement a custom search method to search on the Firm property, and I would like to do this all in code. Don't wanna write a stored procedure (since all the profile properties are stored in 1 database column in the WSAT tool).
Something like this obviously isn't the right way to do it, but here it is to just demonstrate accessing the user's profile properties:
private MembershipUserCollection SearchByFirm(string firmName, MembershipUserCollection allRegisteredUsers)
{
MembershipUserCollection searchResults = new MembershipUserCollection();
foreach (MembershipUser user in allRegisteredUsers)
{
ProfileCommon profile = Profile.GetProfile(user.UserName);
if (profile.Firm.ToLowerInvariant().Contains(firmName.ToLowerInvariant()))
{
searchResults.Add(user);
}
}
return searchResults;
}
Can I turn this into some LINQ goodness?
Well can't you just cast it?
IEnumerable<MembershipUser> searchResults = Membership.GetAllUsers().Cast<MembershipUser>();
Hope this helps you guys
Got some help from a colleague who's good with linq. The challenge here is that MembershipUserCollection doesn't implement IEnumerable< T > (!).
List<MembershipUser> searchResults = allUsers.Where(user =>
Profile.GetProfile(user.UserName).Firm.ToLowerInvariant()
.Contains(firmName.ToLowerInvariant())).ToList();
in this case allUsers is a List which I had to populate with the items in the Membership.GetAllUsers() collection.
Just for the record I created this extension method which I think it kinda works:
namespace WebDibaelsaMVC.Utils.MembershipUserCollectionExtensions
{
public static class MembershipUserCollectionExtensions
{
public static IEnumerable<MembershipUser> Where(this MembershipUserCollection userCollection,Func<MembershipUser,bool> func)
{
foreach (MembershipUser membershipUser in userCollection)
{
if (func(membershipUser))
yield return membershipUser;
}
}
}
}
It also converts the MembershipUserCollection to an IEnumerable<MembershipUser> so all other LINQ methods work afterwards.
There is no built in function provided by microsoft. Here is the example of search membership user with UserName and Email Address
Example:
Just Copy below function and implement it - Done...
Public List<MembershipUser> SearchMembershipUser(string strUserName, String strEmail)
{
IEnumerable<MembershipUser> MUser;
if ((!string.IsNullOrEmpty(strUserName) || !string.IsNullOrEmpty(strEmail)))
{
if (!string.IsNullOrEmpty(strUserName) && !string.IsNullOrEmpty(strEmail))
{
MUser = Membership.GetAllUsers().Cast<MembershipUser>()
.Where(x => x.UserName != CurrentUser && x.UserName == strUserName && x.Email == strEmail);
}
else if (!string.IsNullOrEmpty(strUserName))
{
MUser = Membership.GetAllUsers().Cast<MembershipUser>()
.Where(x => x.UserName != CurrentUser && x.UserName == strUserName);
}
else
{
MUser = Membership.GetAllUsers().Cast<MembershipUser>()
.Where(x => x.UserName != CurrentUser && x.Email == strEmail);
}
}
else
{
MUser = Membership.GetAllUsers().Cast<MembershipUser>().Where(x => x.UserName != CurrentUser);
}
return MUser.OrderBy(x => x.UserName).ToList();
}

Resources