I have a project consisting of 2 parts:
ASP.NET API using Entity Framework
.NET MAUI Client App
I use DTOs for comunication from/to the API in order not to expose other properties of my entities. Thanks to this approach I was able to separate Entity data and data that are sent from the API.
At first I used these DTOs also in the MAUI UI. But after some time I started to notice that they contains UI-specific properties, attributes or methods that have no purpose for the API itself, so they are redundant in requests.
EXAMPLE:
1 - API will receive request from MAUI to get exercise based on it's name
2- ExerciseService returns: ExerciseEntity and ExerciseController use AutoMapper to Map ExerciseEntity -> ExerciseDto ommiting ExerciseId field (only admin can see this info in the DB) and returning it in the API response
3 - MAUI receives from the API ExerciseDto. But in the client side it also want to know if data from ExerciseDto are collapsed in the UI. So because of that I add IsCollapsed property into the ExerciseDto. But now this is a redundant property for the API, because I dont want to persist this information in the database.
QUESTIONS:
Should I map these DTOs to new objects on the client side ?
Or how to approach this problem ?
Is there an easier way how to achieve the separation ?
Because having another mapping layer will add extra complexity and a lot of duplicate properties between DTOs and those new client objects.
Normally if you use clean architecture approach your DTOs shoud contain no attributes and other specific data relevant just for some of your projects, to be freely usable by other projects in a form of dependency.
Then you'd have different approaches to consume DTOs in a xamarin/maui application, for example:
APPROACH 1.
Mapping (of course) into a class that is suitable for UI. Here you have some options, use manual mapping, write your own code that uses reflection or use some third party lib using same reflection. Personally using all of them, and when speaking of third party libs Mapster has shown very good to me for api and mobile clients.
APPROACH 2.
Subclass DTO. The basic idea is to deserialize dto into the derived class, then call Init(); if needed. All properties that you manually implemented as new with OnPropertyChanged will update bindings after being popupated by deserializer/mapper and you alse have a backup plan to call RaiseProperties(); for all of the props, even thoses who do not have OnPropertyChanged in place so they can update bindings if any.
Example:
our Api DTO
public class SomeDeviceDTO
{
public int Id { get; set; }
public int Port { get; set; }
public string Name { get; set; }
}
Our derived class for usage in mobile client:
public class SomeDevice : SomeDeviceDTO, IFromDto
{
// we want to be able to change this Name property in run-time and to
// reflect changes so we make it bindable (other props will remain without
// OnPropertyChanged BUT we can always update all bindings in code if needed
// using RaiseProperties();):
private string _name;
public new string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged();
}
}
}
// ADD any properties you need for UI
// ...
#region IFromDto
public void Init()
{
//put any code you'd want to exec after dto's been imported
// for example to fill any new prop with data derived from what you received
}
public void RaiseProperties()
{
var props = this.GetType().GetProperties();
foreach (var property in props)
{
if (property.CanRead)
{
OnPropertyChanged(property.Name);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public interface IFromDto : INotifyPropertyChanged
{
//
// Summary:
// Can initialize model after it's being loaded from dto
void Init();
//
// Summary:
// Notify all properties were updated
void RaiseProperties();
}
We can get it like: var device = JsonConvert.DeserializeObject<SomeDevice>(jsonOfSomeDeviceDTO);
We then can call Init(); if needed..
Feel free to edit this answer to add more approaches..
I am learning how to use the .NET framework. I am working with ASP .NET core. I have never had or hit my azure webhosting quota until recently I keep hitting quota by making very few request and this started ever since I installed dotnetbrowser library. its the best library for my project because it makes getting data easier. however, I will appreciate if someone can tell me how to get same data without using a browser control like web browser or dotnetbrowser. the data I needed go through multiple server and client communications before the needed value is provided. So my question is how can achieve the same thing without using browser control?
finally, my code might be buggy given that I am not too familiar with threads and task. I might be using too much memory. so below is my code
using DotNetBrowser;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Web.Http;
namespace AjaxRequest.Controllers
{
public class ValuesController : ApiController
{
private static ManualResetEvent waitEvent;
private static List<string> ajaxUrls = new List<string>();
static string str = "";
public static Browser browser;
public ValuesController()
{
waitEvent = new ManualResetEvent(false);
browser = BrowserFactory.Create();
browser.Context.NetworkService.ResourceHandler = new AjaxResourceHandler();
browser.Context.NetworkService.NetworkDelegate = new AjaxNetworkDelegate();
}
// GET api/values
public string Get(int id, string title)
{
string Title = title.Replace(" ", "-");
browser.LoadURL(string.Format("https://ba.com/foo/{0}-{1}/something.html", Title, id));
waitEvent.WaitOne();
browser.Dispose();
string Json = Regex.Replace(str, #"\\","");
return Json.Replace("\\\"", "\"");
}
public class AjaxResourceHandler : ResourceHandler
{
//HomeController hc;
public bool CanLoadResource(ResourceParams parameters)
{
if (parameters.ResourceType == ResourceType.XHR && parameters.URL.Contains("https://something.com/ajax/blahblah"))
{
ajaxUrls.Add(parameters.URL);
}
return true;
}
}
public class AjaxNetworkDelegate : DefaultNetworkDelegate
{
//HomeController hc;
public override void OnDataReceived(DataReceivedParams parameters)
{
if (ajaxUrls.Contains(parameters.Url))
{
PrintResponseData(parameters.Data);
}
}
public void PrintResponseData(byte[] data)
{
str = Encoding.UTF8.GetString(data);
ajaxUrls.Clear();
browser.Stop();
browser.dispose();
waitEvent.Set();
}
public void error(string info)
{
str = info;
waitEvent.Set();
}
}
}
}
is it possible that I am doing it wrong? if that's the case how can it be improved to conserve memory or data?
UPDATE: am using azure free hosting services
DotNetBrowser is a Chromium wrapper - I am not entirely sure why you would need it in a web app, but that said, it is likely it is the culprit. Once you remove it, you can use HttpClient to perform the right requests with no memory overhead.
Profiling-wise, your best bet is to start with Application Insights - it's enabled by default in ASP.NET Core projects. It will allow resource tracking across app components.
It seems like you have more than one running Browser instance.
I can suggest to check that Browser instance is disposed correctly. If not, you can try to dispose it in the Dispose method of the controller.
We are using classes inheriting from Registry to configure our StructureMap container in our ASP.NET MVC 4 application startup.
Some excerpt from one of the registry-classes:
For<ISomeInterface>().HybridHttpOrThreadLocalScoped().Use<SomeImplementation>();
We would like use different instances of our interfaces depending on the context. (For example switching from database "online" mode to "maintenance" mode where everything is saved on filesystem; therefore using other interfaces (i.e. repositories) all over the place in our application)
For example by default it should use SomeImplementation but when passing some kind of querystring in the url (to name a simple "context" scenario) it should use SomeOtherImplementation.
How can this be achieved for multiple interfaces/types?
Should we use named instances for this? Like:
For<ISomeInterface>().HybridHttpOrThreadLocalScoped().Use<SomeOtherImplementation>().Named("other");
I read about StructureMap Profiles but i'm not sure if this is the right way to go.
Should we use profiles for this? Like i.e.:
Profile("other", profileExpression =>
{
For<ISomeInterface>().HybridHttpOrThreadLocalScoped().Use<SomeOtherImplementation>();
});
How can we switch different configurations on the fly?
ObjectFactory.Container.SetDefaultsToProfile("other");
This way? (At what stage in mvc "life-cycle" this can happen at the earliest?)
Can this be a temporary switch for just the current request or current users session?
Thanks in advance!
From my experience, runtime configuration like this is best achieved using an abstract factory that is responsible for creating your dependency during runtime.
This dependency can then be registered with StructureMap like so:
Your registry:
public class StorageRegistry : Registry
{
public StorageRegistry()
{
...
this.For<IDataStoreInstance>().Use(ctx => ctx.GetInstance<DataStoreAbstractFactory>().ConfigureStorage());
...
}
}
Now your DataStoreAbstractFactory is responsible for creating and configure the necessary storage instance based on your configuration. As DataStoreAbstractFactory is now registered with StructureMap you're able to inject the necessary dependencies into it for determining which storage method to use.
Implementation example:
public class DataStoreAbstractFactory
{
public DataStoreAbstractFactory()
{
// Dependencies to figure out data storage method can be injected here.
}
public IDataStoreInstance ConfigureStorage()
{
// This method can be used to return type of storage based on your configuration (ie: online or maintenance)
}
}
public interface IDataStoreInstance
{
void Save();
}
public class DatabaseStorage : IDataStoreInstance
{
public void Save()
{
// Implementation details of persisting data in a database
}
}
public class FileStorage : IDataStoreInstance
{
public void Save()
{
// Implementation details of persisting data in a file system
}
}
Usage:
Your controller/services or whatever are now completely unaware of what storage method they're using when accessing and persisting data.
public class UpdateController : Controller
{
public IDataStoreInstance StorageInstance { get; set; }
public UpdateController(IDataStoreInstance storageInstance)
{
StorageInstance = storageInstance;
}
[HttpPost]
public ActionResult Index()
{
...
this.StorageInstance.Save();
...
}
...
}
I have an ASP.NET MVC 4 app that i'm incorporating an OData API into. This is running the 2012.2 stuff with the larger OData support.
I did not use a separate area for this...that might have been a mistake but my app is small and area seemed overkill.
I've got my controllers setup correctly and an example path to my Segments collection (segments is a type in my domain) is "/odata/Segments". This loads as expected and is working.
On my homepage i'm trying to add a link to this resource using Razor's Html.ActionLink (or RouteLink) but it seems the OData controllers layout doesn't quite work with those methods because the controllers are prefixed with "odata" when registered in WebAPIConfig:
config.Routes.MapODataRoute("OData Route", "odata", model );
I can trick the method to construct the correct url by pretending there's an odata controller when there certainly isn't one (as far as i know) with something like this:
#Html.RouteLink("Segments", "Segments", "odata")
but that seems like a hack.
I don't quite understand the ASP.NET routing plumbing well enough to understand how that prefix passed to MapODataRoute is being incorporated into the MVC chain so that i can use the "right" razor method the "right" way.
just for kicks, here's my SegmentsController:
public class SegmentsController : EntitySetController<Segment, long>
{
private MarketerDB db = new MarketerDB();
// GET api/segments
override public IQueryable<Segment> Get()
{
return db.Segments.AsQueryable();
}
protected override Segment GetEntityByKey(long key)
{
return db.Segments.Find(key);
}
public IQueryable<Affiliate> GetAffiliates([FromODataUri] long key)
{
return this.GetEntityByKey(key).Affiliates.AsQueryable();
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
We have an ODataLink method on System.Web.Http.UrlHelper but we forgot to add one to the MVC System.Web.Mvc.UrlHelper. Till we add it, you can use this extension method,
namespace System.Web.Mvc
{
public static class UrlHelperExtensions
{
private static IODataPathHandler _pathHandler = new DefaultODataPathHandler();
public static string ODataUrl(this UrlHelper urlHelper, string routeName, params ODataPathSegment[] segments)
{
string odataPath = _pathHandler.Link(new ODataPath(segments));
return urlHelper.HttpRouteUrl(
routeName,
new RouteValueDictionary() { { ODataRouteConstants.ODataPath, odataPath } });
}
}
}
and call it from your razor views by doing something like (assuming there is an entityset customers and you want to put the navigation link to orders on customers(42)),
#Url.ODataUrl("odata", new EntitySetPathSegment("customers"), new KeyValuePathSegment("42"), new NavigationPathSegment("orders"))
Make sure you have an #using System.Web.Http.OData.Routing directive in your razor view.
Presently I am working using single tier architecture. Now I am wanting to learn how to write code using 3 tier architecture. Please can you provide me with a simple example?
Wikipedia have a nice explanation: Multitier architecture:
'Three-tier' is a client-server architecture in which the user interface, functional process logic ("business rules"), computer data storage and data access are developed and maintained as independent modules, most often on separate platforms.
Web development usage
In the web development field, three-tier is often used to refer to websites, commonly electronic commerce websites, which are built using three tiers:
A front end web server serving static content, and potentially some cached dynamic content.
A middle dynamic content processing and generation level application server, for example Java EE, ASP.net, PHP platform.
A back-end database, comprising both data sets and the database management system or RDBMS software that manages and provides access to the data.
This is what I have in my project. More than just a traditional 3-tier architecture.
1.) Application.Infrastructure
Base classes for all businessobjects, busines object collection, data-access classes and my custom attributes and utilities as extension methods, Generic validation framework. This determines overall behavior organization of my final .net application.
2.) Application.DataModel
Typed Dataset for the Database.
TableAdapters extended to incorporate Transactions and other features I may need.
3.) Application.DataAccess
Data access classes.
Actual place where Database actions are queried using underlying Typed Dataset.
4.) Application.DomainObjects
Business objects and Business object collections.
Enums.
5.) Application.BusinessLayer
Provides manager classes accessible from Presentation layer.
HttpHandlers.
My own Page base class.
More things go here..
6.) Application.WebClient or Application.WindowsClient
My presentation layer
Takes references from Application.BusinessLayer and Application.BusinessObjects.
Application.BusinessObjects are used across the application and they travel across all layers whenever neeeded [except Application.DataModel and Application.Infrastructure]
All my queries are defined only Application.DataModel.
Application.DataAccess returns or takes Business objects as part of any data-access operation. Business objects are created with the help of reflection attributes. Each business object is marked with an attribute mapping to target table in database and properties within the business object are marked with attributes mapping to target coloumn in respective data-base table.
My validation framework lets me validate each field with the help of designated ValidationAttribute.
My framrwork heavily uses Attributes to automate most of the tedious tasks like mapping and validation. I can also new feature as new aspect in the framework.
A sample business object would look like this in my application.
User.cs
[TableMapping("Users")]
public class User : EntityBase
{
#region Constructor(s)
public AppUser()
{
BookCollection = new BookCollection();
}
#endregion
#region Properties
#region Default Properties - Direct Field Mapping using DataFieldMappingAttribute
private System.Int32 _UserId;
private System.String _FirstName;
private System.String _LastName;
private System.String _UserName;
private System.Boolean _IsActive;
[DataFieldMapping("UserID")]
[DataObjectFieldAttribute(true, true, false)]
[NotNullOrEmpty(Message = "UserID From Users Table Is Required.")]
public override int Id
{
get
{
return _UserId;
}
set
{
_UserId = value;
}
}
[DataFieldMapping("UserName")]
[Searchable]
[NotNullOrEmpty(Message = "Username Is Required.")]
public string UserName
{
get
{
return _UserName;
}
set
{
_UserName = value;
}
}
[DataFieldMapping("FirstName")]
[Searchable]
public string FirstName
{
get
{
return _FirstName;
}
set
{
_FirstName = value;
}
}
[DataFieldMapping("LastName")]
[Searchable]
public string LastName
{
get
{
return _LastName;
}
set
{
_LastName = value;
}
}
[DataFieldMapping("IsActive")]
public bool IsActive
{
get
{
return _IsActive;
}
set
{
_IsActive = value;
}
}
#region One-To-Many Mappings
public BookCollection Books { get; set; }
#endregion
#region Derived Properties
public string FullName { get { return this.FirstName + " " + this.LastName; } }
#endregion
#endregion
public override bool Validate()
{
bool baseValid = base.Validate();
bool localValid = Books.Validate();
return baseValid && localValid;
}
}
BookCollection.cs
/// <summary>
/// The BookCollection class is designed to work with lists of instances of Book.
/// </summary>
public class BookCollection : EntityCollectionBase<Book>
{
/// <summary>
/// Initializes a new instance of the BookCollection class.
/// </summary>
public BookCollection()
{
}
/// <summary>
/// Initializes a new instance of the BookCollection class.
/// </summary>
public BookCollection (IList<Book> initialList)
: base(initialList)
{
}
}
By "tier" do you mean a "layer" in your software stack? The word "tier" is better used to describe the physical components of your system. If you are using ASP.NET, you probably already have a "3 tiered" system -
Browser displaying web pages
IIS Server hosting your app
Database Server with your database
But you are possibly putting all of your code into a single software "layer" - specifically, the code behind file of your aspx pages. You want to move from a single layer to a 3 layer approach. The classic "3 layer" software architecture consists of the following -
Presentation Layer
Business Logic Layer (BLL)
Data Access Layer (DAL)
(source: asp.net)
For a typical ASP.NET app, you might apply this as follows. First, you create a LINQ2SQL file (.dbml) containing the objects for your database access. This is your Data Access Layer (DAL).
Next you might create a DLL to contain your Business Logic Layer (BLL). This layer will access the database via the DAL, manipulate it as required, and then expose it via a simple interface. For example, if your application displays a client list, your BLL might have a public function called GetClientList() which returned a list of clients.
Finally you would set up your code behind files to instantiate the BLL and wire it up to the interface components. This is your Presentation Layer. For example, it might take the data returned from your GetClientList() function and bind it to a data grid on the web form. The idea is to have the presentation layer as thin as possible.
This seems a little long-winded to describe, but it's pretty straight-forward once you have done it a couple of times. You will find that separating out your application like this will make it much easier to maintain, as the separation of concerns leads to cleaner code. You will also find it much easier to upgrade or even replace your presentation layer, as it contains very little smarts. Finally, you will get to a point where you have a number of very useful BLL libraries that you can easily consume in new applications, greatly improving productivity.
Presentation layer: put everything that is related to user interface. (What the user sees)
Business layer: everything that is related to the logic of the application (How is the information coming from presentation layer treated)
Data layer: provide an abstraction of the underlying data source(s) (Where and how the information coming from/going to business layer is stored)
Each layer should know as less as possible about the other and it should be a top down approach:
the data layer should know nothing about business and presentation
business layer should know about data but not about presentation
presentation should know about business but not about data
Simple example:
Website:
Presentation: all the graphical things, fields where user inserts data, menus, pictures, etc.
Business: all constraints about the data (unique name, name without symbols, valid date, etc), methods for manipulating business objects (create new user, add new order, etc)
Data: Methods that access the underlying database.
3-tier architecture can have different meanings depending on context. Generally it means that responsibilities in the application are divided between different tiers. Typically, 3-tier refers to :
presentation tier" (actual user interface)
logic tier (application/business logic)
data tier (database, data storage)
The details vary by application.
Wikipedia, as usual, has a nice overview: http://en.wikipedia.org/wiki/Multitier_architecture
A simple example would be a typical business app:
presentation: browser, or fat client
logic tier: business logic, typically in an application server (based on J2EE, ASP.NET or whatever)
data tier: a database, typically a RDBMS such as MySQL or Oracle
A 3-tier architecture usually has the following components:
Client Browser
Web server hosting the ASP.NET application
Some backend storage such as database that is being accessed by the ASP.NET application
So to answer your question on how to write code for a 3-tier architecture, you develop an ASP.NET application that communicates with a data storage.
A good tutorial, with complete source control download of a well written tiered application would be here:
http://nerddinnerbook.s3.amazonaws.com/Intro.htm
This isn't a tutorial about tiered architecture, but it's a well written app and gives some insight into why you might consider this architecture.
Additionally, as has only been briefly touched on above, this is about keeping your logic/storage/presentation code separate, so if you have to change one of them (e.g change from asp.net front end to a desktop application), it's not so hard to do.
Three-tier (layer) is a client-server architecture in which the user interface, business process (business rules) and data storage and data access are developed and maintained as independent modules or most often on separate platforms.
Basically, there are 3 layers:
tier 1 (presentation tier, GUI tier)
tier 2 (business objects, business logic tier)
tier 3 (data access tier). These tiers can be developed and tested separately.
What is the need for dividing the code in 3-tiers? Separation of the user interface from business logic and database access has many advantages. Some of the advantages are as follows:
Reusability of the business logic component results in quick
development. Let's say we have a module that handles adding, updating,
deleting and finding customers in the system. As this component is
developed and tested, we can use it in any other project that might
involve maintaining customers.
Transformation of the system is easy. Since the business logic is
separate from the data access layer, changing the data access layer
won’t affect the business logic module much. Let's say if we are
moving from SQL Server data storage to Oracle there shouldn’t be any
changes required in the business layer component and in the GUI
component.
Change management of the system is easy. Let's say if there is a minor
change in the business logic, we don’t have to install the entire
system in individual user’s PCs. E.g. if GST (TAX) is changed from 10%
to 15% we only need to update the business logic component without
affecting the users and without any downtime.
Having separate functionality servers allows for parallel development
of individual tiers by application specialists.
Provides more flexible resource allocation. Can reduce the network
traffic by having the functionality servers strip data to the precise
structure needed before sending it to the clients.
connection class
-----------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Web .UI.WebControls ;
/// <summary>
/// Summary description for conn
/// </summary>
namespace apm_conn
{
public class conn
{
public SqlConnection getcon()
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["connect"].ConnectionString );
if (con.State == ConnectionState.Closed)
{
con.Open();
}
return con;
}
#region execute command
public string Executecommand(SqlParameter []sqlparm,string sp)
{
string r_val = "";
try
{
SqlConnection con = new SqlConnection();
con = getcon();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = sp;
cmd.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter loopvar_parm in sqlparm)
{
cmd.Parameters.Add(loopvar_parm);
}
cmd.Parameters.Add("#Var_Output", SqlDbType.VarChar, 20).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
r_val = (string)cmd.Parameters["#Var_Output"].Value;
con.Close();
}
catch { }
return r_val;
}
#endregion
#region Execute Dataset
public DataSet ExeccuteDataset(SqlParameter[] sqlParm, string sp)
{
DataSet ds = new DataSet();
try
{
SqlConnection con = new SqlConnection();
con = getConn();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = sp;
foreach (SqlParameter LoopVar_param in sqlParm)
{
cmd.Parameters.Add(LoopVar_param);
}
cmd.ExecuteNonQuery();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
}
catch
{ }
return ds;
}
#endregion
#region grid
public void Bindgrid(DataSet ds,GridView g)
{
try
{
g.DataSource = ds.Tables[0];
g.DataBind();
}
catch { }
}
#endregion
#region Dropdownlist
public void Binddropdown(DropDownList dl,DataSet ds,string text,string value)
{
try
{
dl.DataSource = ds.Tables[0];
dl.DataTextField = text;
dl.DataValueField = value;
dl.DataBind();
}
catch
{}
}
#endregion
public conn()
{
//
// TODO: Add constructor logic here
//
}
}
}
dal
---------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using apm_conn;
using System.Data.SqlClient;
using apm_ent;
/// <summary>
/// Summary description for Class1
/// </summary>
namespace apm_dal
{
public class dal
{
conn ob_conn = new conn();
public dal()
{
//
// TODO: Add constructor logic here
//
}
public string insert(ent obj_ent)
{
SqlParameter[] sqlparm =
{
new SqlParameter ("#Var_Action",obj_ent.Var_Action),
new SqlParameter ("#Int_Id",obj_ent.Int_Id ),
new SqlParameter ("#Var_Product",obj_ent.Var_Product ),
new SqlParameter ("#Dc_Price",obj_ent.Var_Price ),
new SqlParameter ("#Int_Stat",obj_ent.Int_Stat ),
};
return ob_conn.Executecommand(sqlparm, "Proc_product");
}
public string ins(ent obj_ent)
{
SqlParameter[] parm =
{
new SqlParameter ("#Var_Action",obj_ent .Var_Action),
new SqlParameter ("#Int_Id",obj_ent .Int_Id),
};
return ob_conn.Executecommand(parm, "Proc_product");
}
}
}
bal
-------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using apm_ent;
using apm_dal;
/// <summary>
/// Summary description for bal
/// </summary>
namespace apm_Bal
{
public class bal
{
dal ob_dal = new dal();
string r_val = "";
public bal()
{
//
// TODO: Add constructor logic here
//
}
public string insert(ent obj_ent)
{
return ob_dal.insert(obj_ent);
}
}
}
Ent
------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for ent
/// </summary>
namespace apm_ent
{
public class ent
{
public ent()
{
//
// TODO: Add constructor logic here
//
}
#region Ent
public int Int_Id { get; set; }
public string Var_Action { get; set; }
public string Var_Product { get; set; }
public decimal Var_Price { get; set; }
public int Int_Stat { get; set; }
#endregion
}
}
page code
--------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using apm_conn;
using apm_ent;
using apm_Bal;
using apm_conn;
public partial class _Default : System.Web.UI.Page
{
conn obj_conn = new conn();
ent obj_ent = new ent();
bal obj_bal = new bal();
string r_val = "";
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnsub_Click(object sender, EventArgs e)
{
obj_ent.Var_Action = "INS";
obj_ent.Var_Product = txtproduct.Text;
obj_ent.Var_Price = Convert.ToDecimal (txtprice.Text);
r_val = obj_bal.insert(obj_ent);
if (r_val == "1")
{
Response.Write("<script>alert('Inserted Sucessfully')</script>");
}
}
}