Calling dynamic .Include list - asp.net

i am working on an asp.net mvc web application. and i have the following repository method,, where i will be passing the .Include() dynamically :-
public async Task<SecurityRole> FindSecurityRole(int id,string path="")
{
return await context.SecurityRoles.Include(path).SingleOrDefaultAsync(a2 => a2.SecurityRoleID == id);
}
now inside my controller i want to call the above method as follow:-
await uniteofwork.SecurityRoleRepository.FindSecurityRole(id.Value,)
but i am not sure what are the apporachies i can follow to pass the properties ?
Thanks

You can chain calls to things like Include over multiple lines by storing the result in a variable. Nothing will actually hit your database until you call an evaluating expression like SingleOrDefaultAsync here.
var query = context.SecurityRoles;
foreach (var include in path.Split(',', StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(include);
}
return await query.SingleOrDefaultAsync(a2 => a2.SecurityRoleID == id);
Splitting the string allows you to pass multiple include hierarchies at once, comma-delimited.

Related

How do i make this code reusable?

In my application, i have a check, which checks the COUNT of a bunch of database tables. If each of these COUNTS is above a certain threshold, then it sets a property as active. Here is an example of a controller where a user adds room information
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "ID,RoomTypeID,Description")] Room room, int propertyId)
{
if (ModelState.IsValid)
{
room.ID = Guid.NewGuid();
room.DateCreated = DateTime.Now;
room.PropertyID = propertyId;
db.Rooms.Add(room);
await db.SaveChangesAsync();
var roomCount = db.Rooms.Where(r => r.PropertyID == propertyId).Count();
var rateCount = db.Rates.Where(r => r.PropertyID == propertyId).Count();
var imageCount = db.PropertyImage.Where(r => r.PropertyID == propertyId).Count();
if(roomCount >= 3 && rateCount >= 3 && imageCount >= 3)
{
//Set Property as ACTIVE
}
return RedirectToAction("Index");
}
The problem i have, is that i want to run this check (the 3 database COUNTS and the 'if' statement) on a whole bunch of controllers. I don't want to have to duplicate this config on every controller for every action. Also, this check may be susceptible to changing, so i'd like to update it in just one place.
How am i best to go about this? Should i be creating some sort of helper class?
Thanks
You are on the right track. You want to separate that responsibility as much as you can based on your needs, or the levels of separation already established in your application. At a minimum, I would create one class that accesses the DB, and another that contains the logic to make the "if" decision. For instance Controller -> calls Helper -> calls DBAccessor

Web API httpget with many parameters

I am trying to create my first REST service using WEB API to replace some of my postbacks in a web forms asp.net project. In the web forms project, when I browse to a new web page, I always get an ASP.net Application variable and a querystring value that helps me determine which database to connect to. In this old app, it connects to several different databases that all have the same schema and database objects but the data is different in each database
I am not sure the best way to pass these variables to a REST Service or if they should be part of the route or some other method.
So in a REST method like the one below
// GET api/<controller>/5
public string GetCategoryByID(int id)
{
return "value";
}
I can get the category id and pass that to my database layer, but I also need the two variables mentioned above. I will need to obtain these variables in every call to my REST api in order to access the appropriate database. Should I use something like the following:
// GET api/<controller>/5
public string GetCategoryByID(int id, string applicationEnvironment, string organization)
{
return "value";
}
Or should they be part of the route with something like this:
api/{appEnvironment}/{organization}/{controller}/{id}
This seems like a simple problem, but I am having trouble figuring out a solution.
I ended up passing extra parameters with my httpget call. I will probably follow this pattern unless I get some additional feedback.
[HttpGet]
public Company[] GetProgramCompanies(int id, [FromUri] string org, [FromUri] string appEnvir)
{
DataLayer dataAccess = new DataLayer(Utilities.GetConnectionString(org, appEnvir));
IEnumerable<BudgetProgramCompanyListing> companies = dataAccess.GetProgramCompaniesListing(id).OrderBy(o => o.Company_Name);
Company[] returnComps = new Company[companies.Count()];
int count = 0;
foreach (BudgetProgramCompanyListing bpc in companies)
{
returnComps[count] = new Company
{
id = bpc.Company_ID,
name = bpc.Company_Name
};
count++;
}
return returnComps;
}
Calling the above service with this url:
api/programcompanies/6?org=SDSRT&appEnvir=GGGQWRT
In .Net core 1.1 you can specify more parameters in HttGet attribute like this:
[HttpGet("{appEnvironment}/{organization}/{controller}/{id}")]
It may work in other .Net versions too.
I used to follow the below two method to pass multiple parameter in HttpGet
public HttpResponseMessage Get(int id,[FromUri]int DeptID)
{
EmpEntity = new EmpDBEntities();
var entity = EmpEntity.USP_GET_EMPINFO(id, DeptID).ToList();
if(entity.Count()!=0)
{
return Request.CreateResponse(HttpStatusCode.OK, entity);
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Employee With ID=" + id.ToString() + " Notfound");
}
}
and the webapi url will be http://localhost:1384/api/emps?id=1&DeptID=1
in the above methode USP_GET_EMPINFO is the stored procedure with two parameters.
in second method we can use the class with [FromUri] to pass multiple parameter.
the code snippet is as below
public HttpResponseMessage Get(int id,[FromUri]Employee emp)
{
EmpEntity = new EmpDBEntities();
var entity = EmpEntity.USP_GET_EMPINFO(id,emp.DEPTID).ToList();
if(entity.Count()!=0)
{
return Request.CreateResponse(HttpStatusCode.OK, entity);
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Employee With ID=" + id.ToString() + " Notfound");
}
}
and the webapi url will be http://localhost:1384/api/emps?id=1&DEPTID=1
here the DEPTID is one of the property of the class. we can add multiple parameters separated with & in the url
You could also define a model and send that with the request and bind it to a variable in your api function using [FromBody].
Something like:
[HttpGet]
public Company[] GetProgramCompanies([FromBody] YourModel model) { ... }
As explained here Model binding in Asp.Net Core

Validating a field based on a different database table / entity

I am writing an MVC 4 application, and using Entity Framework 4.1. I have a validation question which I cannot seem to find the answer to.
Essentially, I have an Entity (object) called "Product" which contains a field "Name", which must follow strict naming conventions which are defined in a separate Entity called "NamingConvention". When the user enters a value, the system needs to check it against the rules established in the NamingConvention entity, and return an error if need be.
Where should this validation be done, and how? I need to check the NamingConvention entity when doing the validation, which means I would need a database context since I'm referencing a different entity. Is there any validation method which won't require me to create a new context? I was thinking of doing the validation in the Controller, since it already creates a data context, but this doesn't seem like the right place to do it.
Thanks for any help!
I have done things like this using a JQuery post (ajax) call from the webpage where the name is being entered. You then post (the value of name) to a method on your controller which can return a JSON value that contains a flag saying if the validation passed and also a message that you want to return to your user. For example :
Javascript in webpage :
$("#name").change(function () {
var nameVal = $(this).val();
$.post(getRoot() + "/NameController/ValidateName", { name: nameVal },
function (data) {
if (data.valid == "true") {
alert("A valid name was chosen");
} else
{
alert(data.message);
}
}, "json");
});
Controller (NameController) Code :
[HttpPost]
public ActionResult ValidateName(string name)
{
// actual validation carried out in a static utility class (Utils.IsNameValid)
// if you are loading the same validation rules from your table each time
// consider caching the data in the application cache or a static List.
bool nameIsValid = Utils.IsNameValid(name, out string ErrorMessage);
JsonResult result = new JsonResult();
result.Data = new { valid = (nameIsValid "true" : "false"), message = ErrorMessage };
return result;
}
I'm using EF 5 but believe you can use this method ... apologies in advance if I'm misleading you with this answer.
You could do the validation within your context (or a context decorator)
public override int SaveChanges()
{
var products = this.GetChangedProducts();
foreach (var product in products)
{
this.ValidateName(product);
}
return base.SaveChanges();
}
private IEnumerable<Product> GetChangedProducts()
{
return (
from entry in _context.ChangeTracker.Entries()
where entry.State != EntityState.Unchanged
select entry.Entity)
.OfType<Product>();
}
private void ValidateName(Product product)
{
//validate here
}

Alfresco: Custom Share Evaluator based on some custom repo webscripts

So I'd like to write a new set of evaluators in Share based on the result of some repository webscripts.
The current existing Share evaluators are usable through some XML configuration and are related to Alfresco usual meta-data.
But, I'd like to know how to write my own Java evaluator while re using most of the logic already here (BaseEvaluator).
Suppose I have a repository webscript that returns some JSON like {"result" : "true"}:
How do I access it from my custom Evaluator? Mainly how do I access the proxy URL to alfresco webapp from the Spring context?
Do I need to write my own async call in Java?
Where do I find this JSONObject parameter of the required evaluate method?
thanks for your help
See if this helps. This goes into a class that extends BaseEvaluator. Wire the bean in through Spring, then set the evaluator on your actions.
public boolean evaluate(JSONObject jsonObject) {
boolean result = false;
final RequestContext rc = ThreadLocalRequestContext.getRequestContext();
final String userId = rc.getUserId();
try {
final Connector conn = rc.getServiceRegistry().getConnectorService().getConnector("alfresco", userId, ServletUtil.getSession());
final Response response = conn.call("/someco/example?echo=false");
if (response.getStatus().getCode() == Status.STATUS_OK) {
System.out.println(response.getResponse());
try {
org.json.JSONObject json = new org.json.JSONObject(response.getResponse());
result = Boolean.parseBoolean(((String) json.get("result")));
} catch (JSONException je) {
je.printStackTrace();
return false;
}
} else {
System.out.println("Call failed, code:" + response.getStatus().getCode());
return false;
}
} catch (ConnectorServiceException cse) {
cse.printStackTrace();
return false;
}
return result;
}
In this example I am using a simple example web script that echoes back your JSON and switches the result based on the value of the "echo" argument. So when it is called with "false", the JSON returns false and the evaluator returns false.
I should probably point out the name collision between the org.json.simple.JSONObject that the evaluate method expects and the org.json.JSONObject I am using to snag the result from the response JSON.

JsonResult in services layer

In my MVC3 solution I'm wondering how to move the logic that returns Json out of the controller and into the service layer. Say I have the following action in my controller to get the Json needed for a JQueryUI autocomplete control:
public JsonResult ClientAutocompleteJSON(string term)
{
NorthwindEntities db = new NorthwindEntities();
var customers = db.Customers
.Where(c => c.ContactName.Contains(term))
.Take(25)
.Select(c => new
{
id = c.CustomerID,
label = c.ContactName,
value = c.ContactName
});
return Json(customers, JsonRequestBehavior.AllowGet);
}
How would I move this into the service layer? I would prefer not to reference System.Web.MVC in my service layer. I've also thought of returning the customers but I'm not sure how to return the anonymous type - would I have to create a class?
I would not couple your service implementation to a specific (UI) format. It would be better to return a strongly typed customer object and then format this how you want within your Action method.
// Service method
public IEnumerable<Customer> FindCustomers(string term) {
NorthwindEntities db = new NorthwindEntities();
return db.Customers
.Where(c => c.ContactName.Contains(term))
.Take(25)
.ToList();
}
// Action method
public JsonResult ClientAutocompleteJSON(string term) {
var customers = customerService.FindCustomers(term)
.Select(c => new
{
id = c.CustomerID,
label = c.ContactName,
value = c.ContactName
});
return Json(customers, JsonRequestBehavior.AllowGet);
}
This code is much more reusable - for example, you could use the same service method to provide a simple HTML search form.
Create a DTO object: http://martinfowler.com/eaaCatalog/dataTransferObject.html
I know about a feature in Ruby on Rails, there you can define that your method is capable of returning JSON or XML or HTML based on client preference, it will be a good feature if you can find a library that can do this for you. It could be an aspect which by dynamic proxifying your services can do.

Resources