views:

324

answers:

3

I need to make a web application and I want to use MVC. However, my Model can't be one of the standard Models -- the data is not stored in a database but instead in an external application accessible only via a API. Since this is the first MVC application I've implemented I'm relying on examples to understand how to go about it. I can't find any examples of a non-DB based Model. An example of a custom Model would be fine too. Can anyone point me to such a beast? Maybe MVC is just to new and none exist.

It seems like I might be able to get away with the DataSet Model, however I've not seen any examples of how to use this object. I expect an example of DataSet could help me also. (Maybe it is the same thing?)

Please note: I've seen countless examples of custom bindings. This is NOT what I want. I need an example of a custom Model which is not tied to a specific database/table.

UPDATE

I found a good example from MS located here:

http://msdn.microsoft.com/en-us/library/dd405231.aspx

While this is the "answer" to my question, I don't really like it because it ties me to MS's view of the world. @Aaronaught, @jeroenh, and @tvanfosson give much better answers from a meta perspective of moving my understanding (and yours?) forward with respect to using MVC.

I'm giving the check to @Aaronaught because he actually has example code (which I asked for.) Thanks all and feel free to add even better answers if you have one.

+3  A: 

I think what you are looking for is really a non-DB service layer. Models, typically, are relatively simple containers for data, though they may also contain business logic. It really sounds like what you have is a service to communicate with and need a layer to mediate between the service and your application, producing the appropriate model classes from the data returned by the service.

This tutorial may be helpful, but you'd need to replace the repository with your class that interacts with the service (instead of the DB).

tvanfosson
Your first paragraph is exactly on track. That is exactly what I need and what I would like as a code example. It can be really really simple, just an example. Your link is useless, as far as I can tell that talks about and gives examples of doing validation on user input. It is using something called public repository as the model, but does not show the code for that bit.
Hogan
You're using the term model to represent the entirety of the data access layer, it seems. I would call the repository part of the access layer that interacts with the underlying model. The model itself would be the collection of entities that the repository operates on. No matter, but I thought I should point out our terminology differences. The pattern was the thing I was trying to highlight -- not the actual use of the pattern. In the pattern your repository would interact with your API -- make calls to the API to retrieve data and construct the entities (model classes) from the results.
tvanfosson
This is good, I'm trying to understand the terminology, which is not clear it seems from the examples and documentation I've read online.
Hogan
+1  A: 

There is no fixed prescription of what a "Model" in MVC should be, just that it should contain the data that needs to be shown on screen, and probably also manipulated.

In a well-designed MVC application, data access is abstracted away somehow anyway, typically using some form of the Repository pattern: you define an abstraction layer (say, an IRepository interface) that defines the contract needed to get and persist data. The actual implementation will usually call a database, but in your case should call your 'service API'.

Here is an example of an MVC application that calls out to a WCF service.

jeroenh
+2  A: 

In most cases it shouldn't matter what the backing source is for the actual application data; the model should be exactly the same. In fact, one of the main reasons for using something like a repository is so that you can easily change the underlying storage.

For example, I have an MVC app that uses a lot of web services - rarely does it have access to a local database, except for simple things like authentication and user profiles. A typical model class might look like this:

[DataContract(Namespace = "http://services.acme.com")]
public class Customer
{
    [DataMember(Name = "CustomerID")]
    public Guid ID { get; set; }

    [DataMember(Name = "CustomerName")]
    public string Name { get; set; }
}

Then I will have a repository interface that looks like this:

public interface ICustomerRepository
{
    Customer GetCustomerByID(Guid id);
    IList<Customer> List();
}

The "API" is all encapsulated within the concrete repository:

public class AcmeWSCustomerRepository : ICustomerRepository, IDisposable
{
    private Acme.Services.CrmServiceSoapClient client;

    public AcmeWSCustomerRepository()
        : this(new Acme.Services.CrmServiceSoapClient())

    public AcmeWSCustomerRepository(Acme.Services.CrmServiceSoapClient client)
    {
        if (client == null)
            throw new ArgumentNullException("client");
        this.client = client;
    }

    public void Dispose()
    {
        client.SafeClose();    // Extension method to close WCF proxies
    }

    public Customer GetCustomerByID(Guid id)
    {
        return client.GetCustomerByID(id);
    }

    public IList<Customer> List()
    {
        return client.GetAllCustomers();
    }
}

Then I'll also probably have a local testing repository with just a few customers that reads from something like an XML file:

public class LocalCustomerRepository : ICustomerRepository, IDisposable
{
    private XDocument doc;

    public LocalCustomerRepository(string fileName)
    {
        doc = XDocument.Load(fileName);
    }

    public void Dispose()
    {
    }

    public Customer GetCustomerByID(Guid id)
    {
        return
            (from c in doc.Descendants("Customer")
             select new Customer(c.Element("ID").Value, c.Element("Name").Value))
            .FirstOrDefault();
    }

    // etc.
}

The point I'm trying to make here is, well, this isn't tied to any particular database. One possible source in this case is a WCF service; another is a file on disk. Neither one necessarily has a compatible "model". In this case I've assumed that the WCF service exposes a model that I can map to directly with DataContract attributes, but the Linq-to-XML version is pure API; there is no model, it's all custom mapping.

A really good domain model should actually be completely independent of the true data source. I'm always a bit skeptical when people tell me that a Linq to SQL or Entity Framework model is good enough to use throughout the entire application/site. Very often these simply don't match the "human" model and simply creating a bunch of ViewModel classes isn't necessarily the answer.

In a sense, it's actually better if you're not handed an existing relational model. It forces you to really think about the best domain model for your application, and not necessarily the easiest one to map to some database. So if you don't already have a model from a database - build one! Just use POCO classes and decorate with attributes if necessary, then create repositories or services that map this domain model to/from the API.

Aaronaught
This seems to be the only question that directly answered my question, can anyone enlighten me why it did not get more points? (I seem to be only person to give it +1)
Hogan
Because your question has only had 80 views (as of now) and most people won't have read the question through, let alone this answer; and if it answers your question, isn't that the point (sic)?
Unsliced